diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/Cargo.lock rustc-1.59.0+dfsg1~ubuntu1~llvm/Cargo.lock --- rustc-1.58.1+dfsg1~ubuntu1~llvm/Cargo.lock 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/Cargo.lock 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.25.0", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -87,9 +87,9 @@ [[package]] name = "anyhow" -version = "1.0.34" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "array_tool" @@ -175,9 +175,7 @@ "filetime", "getopts", "ignore", - "lazy_static", "libc", - "merge", "num_cpus", "once_cell", "opener", @@ -276,7 +274,7 @@ [[package]] name = "cargo" -version = "0.59.0" +version = "0.60.0" dependencies = [ "anyhow", "atty", @@ -370,7 +368,7 @@ dependencies = [ "directories", "rustc-workspace-hack", - "rustc_version 0.3.3", + "rustc_version", "serde", "serde_json", "vergen", @@ -419,7 +417,7 @@ [[package]] name = "cargo-util" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "core-foundation", @@ -492,9 +490,9 @@ [[package]] name = "chalk-derive" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983193cacd81f0f924acb666b7fe5e1a0d81db9f113fa69203eda7ea8ce8b6c" +checksum = "d54e3b5f9e3425e6b119ff07568d8d006bfa5a8d6f78a9cbc3530b1e962e316c" dependencies = [ "proc-macro2", "quote", @@ -504,9 +502,9 @@ [[package]] name = "chalk-engine" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a171ce5abbf0fbd06f221ab80ab182c7ef78603d23b858bc44e7ce8a86a396" +checksum = "bdc891073396b167163db77123b0a3c00088edc00466cecc5531f33e3e989523" dependencies = [ "chalk-derive", "chalk-ir", @@ -517,9 +515,9 @@ [[package]] name = "chalk-ir" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a522f53af971e7678f472d687e053120157b3ae26e2ebd5ecbc0f5ab124f2cb6" +checksum = "2b79e5a1d04b79311e90c69356a2c62027853906a7e33b3e070b93c055fc3e8a" dependencies = [ "bitflags", "chalk-derive", @@ -528,14 +526,14 @@ [[package]] name = "chalk-solve" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf79fb77a567e456a170f7ec84ea6584163d4ba3f13660cd182013d34ca667c" +checksum = "a5d2a1db6605aba70a58820bd80ac422b218913a510f1a40beef9efc5371ea1d" dependencies = [ "chalk-derive", "chalk-ir", "ena", - "itertools 0.9.0", + "itertools 0.10.1", "petgraph", "rustc-hash", "tracing", @@ -558,11 +556,11 @@ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term 0.12.1", "atty", "bitflags", "strsim", @@ -574,7 +572,7 @@ [[package]] name = "clippy" -version = "0.1.58" +version = "0.1.59" dependencies = [ "cargo_metadata 0.14.0", "clippy_lints", @@ -584,6 +582,7 @@ "filetime", "if_chain", "itertools 0.10.1", + "parking_lot", "quote", "regex", "rustc-workspace-hack", @@ -600,6 +599,7 @@ version = "0.0.1" dependencies = [ "bytecount", + "cargo_metadata 0.14.0", "clap", "indoc", "itertools 0.10.1", @@ -611,13 +611,13 @@ [[package]] name = "clippy_lints" -version = "0.1.58" +version = "0.1.59" dependencies = [ "cargo_metadata 0.14.0", "clippy_utils", "if_chain", "itertools 0.10.1", - "pulldown-cmark 0.8.0", + "pulldown-cmark", "quine-mc_cluskey", "regex-syntax", "rustc-semver", @@ -632,7 +632,7 @@ [[package]] name = "clippy_utils" -version = "0.1.58" +version = "0.1.59" dependencies = [ "if_chain", "rustc-semver", @@ -678,9 +678,9 @@ [[package]] name = "compiler_builtins" -version = "0.1.53" +version = "0.1.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb" +checksum = "a68c69e9451f1df4b215c9588c621670c12286b53e60fb5ec4b59aaa1138d18e" dependencies = [ "cc", "rustc-std-workspace-core", @@ -766,7 +766,7 @@ [[package]] name = "crates-io" -version = "0.33.0" +version = "0.33.1" dependencies = [ "anyhow", "curl", @@ -1159,6 +1159,12 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] name = "filetime" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1447,6 +1453,17 @@ ] [[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] name = "git2" version = "0.13.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1713,9 +1730,12 @@ [[package]] name = "instant" -version = "0.1.6" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] [[package]] name = "itertools" @@ -1900,9 +1920,9 @@ [[package]] name = "libc" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" dependencies = [ "rustc-std-workspace-core", ] @@ -1922,6 +1942,16 @@ ] [[package]] +name = "libloading" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] name = "libm" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1939,9 +1969,9 @@ [[package]] name = "libssh2-sys" -version = "0.2.19" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" +checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" dependencies = [ "cc", "libc", @@ -1992,9 +2022,9 @@ [[package]] name = "lock_api" -version = "0.4.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -2092,9 +2122,9 @@ [[package]] name = "matchers" -version = "0.0.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ "regex-automata", ] @@ -2124,9 +2154,9 @@ [[package]] name = "mdbook" -version = "0.4.12" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0651782b4cc514c3f98c0acf9b5af1101a735bbe1ac6852bb1a90cb91bdf0ed4" +checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6" dependencies = [ "ammonia", "anyhow", @@ -2138,8 +2168,8 @@ "lazy_static", "log", "memchr", - "open", - "pulldown-cmark 0.7.2", + "opener", + "pulldown-cmark", "regex", "serde", "serde_derive", @@ -2147,6 +2177,7 @@ "shlex", "tempfile", "toml", + "topological-sort", ] [[package]] @@ -2206,28 +2237,6 @@ ] [[package]] -name = "merge" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9" -dependencies = [ - "merge_derive", - "num-traits", -] - -[[package]] -name = "merge_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "minifier" version = "0.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2284,7 +2293,7 @@ "measureme 9.1.2", "rand 0.8.4", "rustc-workspace-hack", - "rustc_version 0.4.0", + "rustc_version", "shell-escape", "smallvec", ] @@ -2348,6 +2357,18 @@ ] [[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "crc32fast", + "flate2", + "indexmap", + "memchr", +] + +[[package]] name = "odht" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2375,15 +2396,6 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "open" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48" -dependencies = [ - "winapi", -] - -[[package]] name = "opener" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2511,9 +2523,9 @@ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -2522,9 +2534,9 @@ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", @@ -2796,9 +2808,9 @@ [[package]] name = "pulldown-cmark" -version = "0.7.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55" +checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" dependencies = [ "bitflags", "getopts", @@ -2807,17 +2819,6 @@ ] [[package]] -name = "pulldown-cmark" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - -[[package]] name = "punycode" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3085,15 +3086,15 @@ "anyhow", "cargo", "cargo-util", - "cargo_metadata 0.12.0", + "cargo_metadata 0.14.0", "clippy_lints", "crossbeam-channel", "difference", - "env_logger 0.7.1", + "env_logger 0.9.0", "futures 0.3.12", "heck", "home", - "itertools 0.9.0", + "itertools 0.10.1", "jsonrpc-core", "lazy_static", "log", @@ -3102,7 +3103,7 @@ "num_cpus", "ordslice", "racer", - "rand 0.7.3", + "rand 0.8.4", "rayon", "regex", "rls-analysis", @@ -3692,6 +3693,7 @@ "rustc_expand", "rustc_feature", "rustc_lexer", + "rustc_lint_defs", "rustc_parse", "rustc_parse_format", "rustc_session", @@ -3708,6 +3710,7 @@ "bitflags", "cstr", "libc", + "libloading", "measureme 10.0.0", "rustc-demangle", "rustc_arena", @@ -3728,7 +3731,6 @@ "rustc_span", "rustc_target", "smallvec", - "snap", "tracing", ] @@ -3741,10 +3743,11 @@ "itertools 0.9.0", "jobserver", "libc", - "object", + "object 0.26.2", "pathdiff", "regex", "rustc_apfloat", + "rustc_arena", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -3763,7 +3766,9 @@ "rustc_symbol_mangling", "rustc_target", "smallvec", + "snap", "tempfile", + "thorin-dwp", "tracing", ] @@ -3823,7 +3828,6 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ - "atty", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3837,6 +3841,7 @@ "rustc_hir_pretty", "rustc_interface", "rustc_lint", + "rustc_log", "rustc_metadata", "rustc_middle", "rustc_parse", @@ -3848,8 +3853,6 @@ "rustc_target", "rustc_typeck", "tracing", - "tracing-subscriber", - "tracing-tree", "winapi", ] @@ -3967,6 +3970,7 @@ "arrayvec", "rustc_macros", "rustc_serialize", + "smallvec", ] [[package]] @@ -3992,6 +3996,7 @@ version = "0.0.0" dependencies = [ "libc", + "libloading", "rustc-rayon", "rustc-rayon-core", "rustc_ast", @@ -4091,6 +4096,17 @@ ] [[package]] +name = "rustc_log" +version = "0.0.0" +dependencies = [ + "atty", + "rustc_span", + "tracing", + "tracing-subscriber", + "tracing-tree", +] + +[[package]] name = "rustc_macros" version = "0.1.0" dependencies = [ @@ -4104,7 +4120,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "libc", + "libloading", "odht", "rustc_ast", "rustc_attr", @@ -4124,7 +4140,6 @@ "smallvec", "snap", "tracing", - "winapi", ] [[package]] @@ -4297,6 +4312,7 @@ name = "rustc_plugin_impl" version = "0.0.0" dependencies = [ + "libloading", "rustc_ast", "rustc_errors", "rustc_hir", @@ -4592,15 +4608,6 @@ [[package]] name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" @@ -4616,7 +4623,7 @@ "expect-test", "itertools 0.9.0", "minifier", - "pulldown-cmark 0.8.0", + "pulldown-cmark", "rayon", "regex", "rustdoc-json-types", @@ -5006,7 +5013,7 @@ "hermit-abi", "libc", "miniz_oxide", - "object", + "object 0.26.2", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5070,9 +5077,9 @@ [[package]] name = "structopt" -version = "0.3.16" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5472fb24d7e80ae84a7801b7978f95a19ec32cb1876faea59ab711eb901976" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ "clap", "lazy_static", @@ -5081,9 +5088,9 @@ [[package]] name = "structopt-derive" -version = "0.4.9" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0eb37335aeeebe51be42e2dc07f031163fbabfa6ac67d7ea68b5c2f68d5f99" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", @@ -5123,9 +5130,9 @@ [[package]] name = "synstructure" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", @@ -5262,18 +5269,18 @@ [[package]] name = "thiserror" -version = "1.0.20" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.20" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -5281,6 +5288,18 @@ ] [[package]] +name = "thorin-dwp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039d1fc0bfdb73910c2702893515580e38c192f47a987bc98ddd38a36f2d953a" +dependencies = [ + "gimli 0.26.1", + "indexmap", + "object 0.27.1", + "tracing", +] + +[[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5394,6 +5413,12 @@ ] [[package]] +name = "topological-sort" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" + +[[package]] name = "tower-service" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5401,9 +5426,9 @@ [[package]] name = "tracing" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5413,9 +5438,9 @@ [[package]] name = "tracing-attributes" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ "proc-macro2", "quote", @@ -5443,48 +5468,33 @@ ] [[package]] -name = "tracing-serde" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] name = "tracing-subscriber" -version = "0.2.16" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab8966ac3ca27126141f7999361cc97dd6fb4b71da04c02044fa9045d98bb96" +checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3" dependencies = [ "ansi_term 0.12.1", - "chrono", "lazy_static", "matchers", "parking_lot", "regex", - "serde", - "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", - "tracing-serde", ] [[package]] name = "tracing-tree" -version = "0.1.9" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967" +checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7" dependencies = [ "ansi_term 0.12.1", "atty", - "termcolor", - "tracing", + "tracing-core", "tracing-log", "tracing-subscriber", ] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc/src/main.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc/src/main.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc/src/main.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc/src/main.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,25 +1,32 @@ -// Configure jemalloc as the `global_allocator` when configured. This is -// so that we use the sized deallocation apis jemalloc provides -// (namely `sdallocx`). +// A note about jemalloc: rustc uses jemalloc when built for CI and +// distribution. The obvious way to do this is with the `#[global_allocator]` +// mechanism. However, for complicated reasons (see +// https://github.com/rust-lang/rust/pull/81782#issuecomment-784438001 for some +// details) that mechanism doesn't work here. Also, we must use a consistent +// allocator across the rustc <-> llvm boundary, and `#[global_allocator]` +// wouldn't provide that. // -// The symbol overrides documented below are also performed so that we can -// ensure that we use a consistent allocator across the rustc <-> llvm boundary -#[cfg(feature = "jemalloc")] -#[global_allocator] -static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - +// Instead, we use a lower-level mechanism. rustc is linked with jemalloc in a +// way such that jemalloc's implementation of `malloc`, `free`, etc., override +// the libc allocator's implementation. This means that Rust's `System` +// allocator, which calls `libc::malloc()` et al., is actually calling into +// jemalloc. +// +// A consequence of not using `GlobalAlloc` (and the `tikv-jemallocator` crate +// provides an impl of that trait, which is called `Jemalloc`) is that we +// cannot use the sized deallocation APIs (`sdallocx`) that jemalloc provides. +// It's unclear how much performance is lost because of this. +// +// As for the symbol overrides in `main` below: we're pulling in a static copy +// of jemalloc. We need to actually reference its symbols for it to get linked. +// The two crates we link to here, `std` and `rustc_driver`, are both dynamic +// libraries. So we must reference jemalloc symbols one way or another, because +// this file is the only object code in the rustc executable. #[cfg(feature = "tikv-jemalloc-sys")] use tikv_jemalloc_sys as jemalloc_sys; fn main() { - // Pull in jemalloc when enabled. - // - // Note that we're pulling in a static copy of jemalloc which means that to - // pull it in we need to actually reference its symbols for it to get - // linked. The two crates we link to here, std and rustc_driver, are both - // dynamic libraries. That means to pull in jemalloc we actually need to - // reference allocation symbols one way or another (as this file is the only - // object code in the rustc executable). + // See the comment at the top of this file for an explanation of this. #[cfg(feature = "tikv-jemalloc-sys")] { use std::os::raw::{c_int, c_void}; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_apfloat/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_apfloat/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_apfloat/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_apfloat/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -33,7 +33,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![no_std] #![forbid(unsafe_code)] -#![feature(iter_zip)] #![feature(nll)] #[macro_use] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast_like.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast_like.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast_like.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast_like.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ use super::ptr::P; use super::token::Nonterminal; use super::tokenstream::LazyTokenStream; -use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; +use super::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt}; use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; use super::{AttrVec, Attribute, Stmt, StmtKind}; @@ -276,7 +276,7 @@ // These ast nodes only support inert attributes, so they don't // store tokens (since nothing can observe them) derive_has_attrs_no_tokens! { - FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam + FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam, Crate } // These AST nodes don't support attributes, but can diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/ast.rs 2022-02-23 04:07:21.000000000 +0000 @@ -332,10 +332,7 @@ pub enum ParamKindOrd { Lifetime, Type, - // `unordered` is only `true` if `sess.unordered_const_ty_params()` - // returns true. Specifically, if it's only `min_const_generics`, it will still require - // ordering consts after types. - Const { unordered: bool }, + Const, // `Infer` is not actually constructed directly from the AST, but is implicitly constructed // during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last. Infer, @@ -346,11 +343,7 @@ use ParamKindOrd::*; let to_int = |v| match v { Lifetime => 0, - Infer | Type | Const { unordered: true } => 1, - // technically both consts should be ordered equally, - // but only one is ever encountered at a time, so this is - // fine. - Const { unordered: false } => 2, + Infer | Type | Const => 1, }; to_int(*self).cmp(&to_int(*other)) @@ -517,6 +510,10 @@ pub attrs: Vec, pub items: Vec>, pub span: Span, + /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold + /// expansion placeholders or an unassigned value (`DUMMY_NODE_ID`) before that. + pub id: NodeId, + pub is_placeholder: bool, } /// Possible values inside of compile-time attribute lists. @@ -1979,7 +1976,7 @@ bitflags::bitflags! { #[derive(Encodable, Decodable, HashStable_Generic)] - pub struct InlineAsmOptions: u8 { + pub struct InlineAsmOptions: u16 { const PURE = 1 << 0; const NOMEM = 1 << 1; const READONLY = 1 << 2; @@ -1988,6 +1985,7 @@ const NOSTACK = 1 << 5; const ATT_SYNTAX = 1 << 6; const RAW = 1 << 7; + const MAY_UNWIND = 1 << 8; } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/attr/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/attr/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/attr/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/attr/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -136,15 +136,15 @@ pub fn value_str(&self) -> Option { match self.kind { - AttrKind::Normal(ref item, _) => item.meta(self.span).and_then(|meta| meta.value_str()), + AttrKind::Normal(ref item, _) => item.meta_kind().and_then(|kind| kind.value_str()), AttrKind::DocComment(..) => None, } } pub fn meta_item_list(&self) -> Option> { match self.kind { - AttrKind::Normal(ref item, _) => match item.meta(self.span) { - Some(MetaItem { kind: MetaItemKind::List(list), .. }) => Some(list), + AttrKind::Normal(ref item, _) => match item.meta_kind() { + Some(MetaItemKind::List(list)) => Some(list), _ => None, }, AttrKind::DocComment(..) => None, @@ -228,6 +228,10 @@ span, }) } + + pub fn meta_kind(&self) -> Option { + Some(MetaItemKind::from_mac_args(&self.args)?) + } } impl Attribute { @@ -242,7 +246,7 @@ match self.kind { AttrKind::DocComment(.., data) => Some(data), AttrKind::Normal(ref item, _) if item.path == sym::doc => { - item.meta(self.span).and_then(|meta| meta.value_str()) + item.meta_kind().and_then(|kind| kind.value_str()) } _ => None, } @@ -270,6 +274,13 @@ } } + pub fn meta_kind(&self) -> Option { + match self.kind { + AttrKind::Normal(ref item, _) => item.meta_kind(), + AttrKind::DocComment(..) => None, + } + } + pub fn tokens(&self) -> AttrAnnotatedTokenStream { match self.kind { AttrKind::Normal(_, ref tokens) => tokens @@ -436,6 +447,16 @@ } impl MetaItemKind { + pub fn value_str(&self) -> Option { + match self { + MetaItemKind::NameValue(ref v) => match v.kind { + LitKind::Str(ref s, _) => Some(*s), + _ => None, + }, + _ => None, + } + } + pub fn mac_args(&self, span: Span) -> MacArgs { match self { MetaItemKind::Word => MacArgs::Empty, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,6 @@ #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] -#![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] #![feature(min_specialization)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/mut_visit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/mut_visit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/mut_visit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/mut_visit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,5 @@ //! A `MutVisitor` represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor` +//! mutates it in place. So, for instance, macro expansion is a `MutVisitor` //! that walks over an AST and modifies it. //! //! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on @@ -14,13 +14,14 @@ use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::thin_vec::ThinVec; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::Span; use smallvec::{smallvec, Array, SmallVec}; use std::ops::DerefMut; -use std::{panic, process, ptr}; +use std::{panic, ptr}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -283,19 +284,21 @@ /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful /// when using a `flat_map_*` or `filter_map_*` method within a `visit_` -/// method. Abort the program if the closure panics. +/// method. // // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_clobber(t: &mut T, f: F) -where - F: FnOnce(T) -> T, -{ +pub fn visit_clobber(t: &mut T, f: impl FnOnce(T) -> T) { unsafe { // Safe because `t` is used in a read-only fashion by `read()` before // being overwritten by `write()`. let old_t = ptr::read(t); - let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))) - .unwrap_or_else(|_| process::abort()); + let new_t = + panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))).unwrap_or_else(|err| { + // Set `t` to some valid but possible meaningless value, + // and pass the fatal error further. + ptr::write(t, T::dummy()); + panic::resume_unwind(err); + }); ptr::write(t, new_t); } } @@ -1105,36 +1108,12 @@ visit_unsafety(unsafety, vis); } -// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible, -// or make crate visiting first class if necessary. pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { - visit_clobber(krate, |Crate { attrs, items, span }| { - let item_vis = - Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; - let item = P(Item { - ident: Ident::empty(), - attrs, - id: DUMMY_NODE_ID, - vis: item_vis, - span, - kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)), - tokens: None, - }); - let items = vis.flat_map_item(item); - - let len = items.len(); - if len == 0 { - Crate { attrs: vec![], items: vec![], span } - } else if len == 1 { - let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); - match kind { - ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span }, - _ => panic!("visitor converted a module to not a module"), - } - } else { - panic!("a crate cannot expand to more than one item"); - } - }); + let Crate { attrs, items, span, id, is_placeholder: _ } = krate; + vis.visit_id(id); + visit_attrs(attrs, vis); + items.flat_map_in_place(|item| vis.flat_map_item(item)); + vis.visit_span(span); } // Mutates one item into possibly many items. @@ -1475,3 +1454,109 @@ } vis.visit_span(&mut visibility.span); } + +/// Some value for the AST node that is valid but possibly meaningless. +pub trait DummyAstNode { + fn dummy() -> Self; +} + +impl DummyAstNode for Option { + fn dummy() -> Self { + Default::default() + } +} + +impl DummyAstNode for P { + fn dummy() -> Self { + P(DummyAstNode::dummy()) + } +} + +impl DummyAstNode for ThinVec { + fn dummy() -> Self { + Default::default() + } +} + +impl DummyAstNode for Item { + fn dummy() -> Self { + Item { + attrs: Default::default(), + id: DUMMY_NODE_ID, + span: Default::default(), + vis: Visibility { + kind: VisibilityKind::Public, + span: Default::default(), + tokens: Default::default(), + }, + ident: Ident::empty(), + kind: ItemKind::ExternCrate(None), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Expr { + fn dummy() -> Self { + Expr { + id: DUMMY_NODE_ID, + kind: ExprKind::Err, + span: Default::default(), + attrs: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Ty { + fn dummy() -> Self { + Ty { + id: DUMMY_NODE_ID, + kind: TyKind::Err, + span: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Pat { + fn dummy() -> Self { + Pat { + id: DUMMY_NODE_ID, + kind: PatKind::Wild, + span: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Stmt { + fn dummy() -> Self { + Stmt { id: DUMMY_NODE_ID, kind: StmtKind::Empty, span: Default::default() } + } +} + +impl DummyAstNode for Block { + fn dummy() -> Self { + Block { + stmts: Default::default(), + id: DUMMY_NODE_ID, + rules: BlockCheckMode::Default, + span: Default::default(), + tokens: Default::default(), + could_be_bare_literal: Default::default(), + } + } +} + +impl DummyAstNode for Crate { + fn dummy() -> Self { + Crate { + attrs: Default::default(), + items: Default::default(), + span: Default::default(), + id: DUMMY_NODE_ID, + is_placeholder: Default::default(), + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/util/literal.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/util/literal.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/util/literal.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/util/literal.rs 2022-02-23 04:07:21.000000000 +0000 @@ -35,12 +35,12 @@ LitKind::Bool(symbol == kw::True) } token::Byte => { - return unescape_byte(&symbol.as_str()) + return unescape_byte(symbol.as_str()) .map(LitKind::Byte) .map_err(|_| LitError::LexerError); } token::Char => { - return unescape_char(&symbol.as_str()) + return unescape_char(symbol.as_str()) .map(LitKind::Char) .map_err(|_| LitError::LexerError); } @@ -57,7 +57,7 @@ // string in the token. let s = symbol.as_str(); let symbol = - if s.contains(&['\\', '\r'][..]) { + if s.contains(&['\\', '\r']) { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/visit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/visit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/visit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast/src/visit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -211,6 +211,9 @@ fn visit_pat_field(&mut self, fp: &'ast PatField) { walk_pat_field(self, fp) } + fn visit_crate(&mut self, krate: &'ast Crate) { + walk_crate(self, krate) + } } #[macro_export] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -49,11 +49,27 @@ .struct_span_err(sp, "the `att_syntax` option is only supported on x86") .emit(); } + if asm.options.contains(InlineAsmOptions::MAY_UNWIND) + && !self.sess.features_untracked().asm_unwind + { + feature_err( + &self.sess.parse_sess, + sym::asm_unwind, + sp, + "the `may_unwind` option is unstable", + ) + .emit(); + } let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + |feature| self.sess.target_features.contains(&Symbol::intern(feature)), + &self.sess.target, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/block.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/block.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/block.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/block.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,6 @@ use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; use rustc_session::parse::feature_err; -use rustc_span::symbol::Ident; use rustc_span::{sym, DesugaringKind}; use smallvec::SmallVec; @@ -39,8 +38,7 @@ let hir_id = self.lower_node_id(s.id); match &local.kind { LocalKind::InitElse(init, els) => { - let (s, e) = self.lower_let_else(hir_id, local, init, els, tail); - stmts.push(s); + let e = self.lower_let_else(hir_id, local, init, els, tail); expr = Some(e); // remaining statements are in let-else expression break; @@ -125,36 +123,25 @@ init: &Expr, els: &Block, tail: &[Stmt], - ) -> (hir::Stmt<'hir>, &'hir hir::Expr<'hir>) { + ) -> &'hir hir::Expr<'hir> { let ty = local .ty .as_ref() .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding))); let span = self.lower_span(local.span); let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None); - let init = Some(self.lower_expr(init)); - let val = Ident::with_dummy_span(sym::val); - let (pat, val_id) = - self.pat_ident_binding_mode(span, val, hir::BindingAnnotation::Unannotated); + let init = self.lower_expr(init); let local_hir_id = self.lower_node_id(local.id); self.lower_attrs(local_hir_id, &local.attrs); - // first statement which basically exists for the type annotation - let stmt = { - let local = self.arena.alloc(hir::Local { + let let_expr = { + let lex = self.arena.alloc(hir::Let { hir_id: local_hir_id, + pat: self.lower_pat(&local.pat), ty, - pat, init, span, - source: hir::LocalSource::Normal, }); - let kind = hir::StmtKind::Local(local); - hir::Stmt { hir_id: stmt_hir_id, kind, span } - }; - let let_expr = { - let scrutinee = self.expr_ident(span, val, val_id); - let let_kind = hir::ExprKind::Let(self.lower_pat(&local.pat), scrutinee, span); - self.arena.alloc(self.expr(span, let_kind, AttrVec::new())) + self.arena.alloc(self.expr(span, hir::ExprKind::Let(lex), AttrVec::new())) }; let then_expr = { let (stmts, expr) = self.lower_stmts(tail); @@ -165,9 +152,10 @@ let block = self.lower_block(els, false); self.arena.alloc(self.expr_block(block, AttrVec::new())) }; + self.alias_attrs(let_expr.hir_id, local_hir_id); self.alias_attrs(else_expr.hir_id, local_hir_id); let if_expr = self.arena.alloc(hir::Expr { - hir_id: self.next_id(), + hir_id: stmt_hir_id, span, kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), }); @@ -180,6 +168,6 @@ ) .emit(); } - (stmt, if_expr) + if_expr } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/expr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/expr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/expr.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/expr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,6 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; -use rustc_session::parse::feature_err; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -35,7 +34,7 @@ } ExprKind::Repeat(ref expr, ref count) => { let expr = self.lower_expr(expr); - let count = self.lower_anon_const(count); + let count = self.lower_array_length(count); hir::ExprKind::Repeat(expr, count) } ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), @@ -92,11 +91,15 @@ let ohs = self.lower_expr(ohs); hir::ExprKind::AddrOf(k, m, ohs) } - ExprKind::Let(ref pat, ref scrutinee, span) => hir::ExprKind::Let( - self.lower_pat(pat), - self.lower_expr(scrutinee), - self.lower_span(span), - ), + ExprKind::Let(ref pat, ref scrutinee, span) => { + hir::ExprKind::Let(self.arena.alloc(hir::Let { + hir_id: self.next_id(), + span: self.lower_span(span), + pat: self.lower_pat(pat), + ty: None, + init: self.lower_expr(scrutinee), + })) + } ExprKind::If(ref cond, ref then, ref else_opt) => { self.lower_expr_if(cond, then, else_opt.as_deref()) } @@ -130,7 +133,15 @@ hir::AsyncGeneratorKind::Block, |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), - ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), + ExprKind::Await(ref expr) => { + let span = if expr.span.hi() < e.span.hi() { + expr.span.shrink_to_hi().with_hi(e.span.hi()) + } else { + // this is a recovered `await expr` + e.span + }; + self.lower_expr_await(span, expr) + } ExprKind::Closure( capture_clause, asyncness, @@ -479,8 +490,12 @@ expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = - self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new())); + let constructor = self.arena.alloc(self.expr_lang_item_path( + method_span, + lang_item, + ThinVec::new(), + None, + )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } @@ -584,8 +599,12 @@ // `future::from_generator`: let unstable_span = self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let gen_future = - self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new()); + let gen_future = self.expr_lang_item_path( + unstable_span, + hir::LangItem::FromGenerator, + ThinVec::new(), + None, + ); // `future::from_generator(generator)`: hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator]) @@ -593,7 +612,7 @@ /// Desugar `.await` into: /// ```rust - /// match { + /// match ::std::future::IntoFuture::into_future() { /// mut pinned => loop { /// match unsafe { ::std::future::Future::poll( /// <::std::pin::Pin>::new_unchecked(&mut pinned), @@ -607,6 +626,7 @@ /// } /// ``` fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { + let dot_await_span = expr.span.shrink_to_hi().to(await_span); match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { @@ -623,13 +643,14 @@ err.emit(); } } - let span = self.mark_span_with_reason(DesugaringKind::Await, await_span, None); + let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, await_span, self.allow_gen_future.clone(), ); - let expr = self.lower_expr(expr); + let expr = self.lower_expr_mut(expr); + let expr_hir_id = expr.hir_id; let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = @@ -656,16 +677,19 @@ span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_pinned], + Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], + Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], + Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -678,18 +702,28 @@ let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = self.expr_ident(span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(span, x_pat); - let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); + let ready_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollReady, + ready_field, + Some(expr_hir_id), + ); let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(span, expr_break, ThinVec::new())) }); self.arm(ready_pat, break_x) }; // `::std::task::Poll::Pending => {}` let pending_arm = { - let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); + let pending_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollPending, + &[], + Some(expr_hir_id), + ); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) }; @@ -709,7 +743,7 @@ let unit = self.expr_unit(span); let yield_expr = self.expr( span, - hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }), + hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), ThinVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -746,10 +780,27 @@ // mut pinned => loop { ... } let pinned_arm = self.arm(pinned_pat, loop_expr); - // match { + // `match ::std::future::IntoFuture::into_future() { ... }` + let into_future_span = self.mark_span_with_reason( + DesugaringKind::Await, + await_span, + self.allow_into_future.clone(), + ); + let into_future_expr = self.expr_call_lang_item_fn( + into_future_span, + hir::LangItem::IntoFutureIntoFuture, + arena_vec![self; expr], + Some(expr_hir_id), + ); + + // match { // mut pinned => loop { .. } // } - hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar) + hir::ExprKind::Match( + into_future_expr, + arena_vec![self; pinned_arm], + hir::MatchSource::AwaitDesugar, + ) } fn lower_expr_closure( @@ -914,24 +965,6 @@ self.lower_span(eq_sign_span), ); } - if !self.sess.features_untracked().destructuring_assignment { - let mut err = feature_err( - &self.sess.parse_sess, - sym::destructuring_assignment, - eq_sign_span, - "destructuring assignments are unstable", - ); - err.span_label(lhs.span, "cannot assign to this expression"); - if self.is_in_loop_condition { - err.span_suggestion_verbose( - lhs.span.shrink_to_lo(), - "you might have meant to use pattern destructuring", - "let ".to_string(), - rustc_errors::Applicability::MachineApplicable, - ); - } - err.emit(); - } let mut assignments = vec![]; @@ -1144,7 +1177,8 @@ fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span)); + let fn_path = + hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) @@ -1178,7 +1212,7 @@ ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))), + self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), fields, None, ) @@ -1373,6 +1407,7 @@ head_span, hir::LangItem::IteratorNext, arena_vec![self; ref_mut_iter], + None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1401,6 +1436,7 @@ head_span, hir::LangItem::IntoIterIntoIter, arena_vec![self; head], + None, ) }; @@ -1456,6 +1492,7 @@ unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], + None, ) }; @@ -1612,8 +1649,10 @@ span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new())); + let path = + self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1622,8 +1661,9 @@ span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args)) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) } fn expr_lang_item_path( @@ -1631,10 +1671,11 @@ span: Span, lang_item: hir::LangItem, attrs: AttrVec, + hir_id: Option, ) -> hir::Expr<'hir> { self.expr( span, - hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))), + hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), attrs, ) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/item.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/item.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/item.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/item.rs 2022-02-23 04:07:21.000000000 +0000 @@ -247,12 +247,7 @@ AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some((fn_def_id.to_def_id(), idty)), - true, - ret_id, - ) + this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) }, ); let sig = hir::FnSig { @@ -1264,7 +1259,7 @@ |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id.to_def_id(), idty)), + Some((fn_def_id, idty)), impl_trait_return_allow, is_async, ) @@ -1283,7 +1278,7 @@ } pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { - abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| { + abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|| { self.error_on_invalid_abi(abi); abi::Abi::Rust }) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -32,7 +32,6 @@ #![feature(crate_visibility_modifier)] #![feature(box_patterns)] -#![feature(iter_zip)] #![feature(never_type)] #![recursion_limit = "256"] @@ -47,20 +46,19 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; -use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName}; +use rustc_hir::{ConstArg, GenericArg, ParamName}; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; -use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::LintBuffer; +use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; -use rustc_span::edition::Edition; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -70,10 +68,9 @@ use tracing::{debug, trace}; macro_rules! arena_vec { - ($this:expr; $($x:expr),*) => ({ - let a = [$($x),*]; - $this.arena.alloc_from_iter(std::array::IntoIter::new(a)) - }); + ($this:expr; $($x:expr),*) => ( + $this.arena.alloc_from_iter([$($x),*]) + ); } mod asm; @@ -162,6 +159,7 @@ allow_try_trait: Option>, allow_gen_future: Option>, + allow_into_future: Option>, } pub trait ResolverAstLowering { @@ -228,7 +226,7 @@ ReturnPositionOpaqueTy { /// `DefId` for the parent function, used to look up necessary /// information later. - fn_def_id: DefId, + fn_def_id: LocalDefId, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, @@ -320,6 +318,7 @@ in_scope_lifetimes: Vec::new(), allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), + allow_into_future: Some([sym::into_future][..].into()), } .lower_crate(krate) } @@ -645,31 +644,16 @@ /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_def_id: LocalDefId, - anonymous_lifetime_mode: AnonymousLifetimeMode, - f: impl FnOnce(&mut Self) -> (Vec>, T), - ) -> (Vec>, T) { - assert!(!self.is_collecting_in_band_lifetimes); - assert!(self.lifetimes_to_define.is_empty()); - let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; - - self.anonymous_lifetime_mode = anonymous_lifetime_mode; - self.is_collecting_in_band_lifetimes = true; - - let (in_band_ty_params, res) = f(self); - - self.is_collecting_in_band_lifetimes = false; - self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - - let lifetimes_to_define = self.lifetimes_to_define.split_off(0); + f: impl FnOnce(&mut Self) -> T, + ) -> (Vec<(Span, ParamName)>, T) { + let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true); + let len = self.lifetimes_to_define.len(); - let params = lifetimes_to_define - .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) - .chain(in_band_ty_params.into_iter()) - .collect(); + let res = f(self); - (params, res) + let lifetimes_to_define = self.lifetimes_to_define.split_off(len); + self.is_collecting_in_band_lifetimes = was_collecting; + (lifetimes_to_define, res) } /// Converts a lifetime into a new generic parameter. @@ -784,27 +768,39 @@ anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { - let mut params = Vec::new(); - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // in-band-lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), - ); - let res = f(this, &mut params); - (params, (generics, res)) + let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self + .collect_in_band_defs(|this| { + this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| { + this.with_in_scope_lifetime_defs(&generics.params, |this| { + let mut impl_trait_defs = Vec::new(); + // Note: it is necessary to lower generics *before* calling `f`. + // When lowering `async fn`, there's a final step when lowering + // the return type that assumes that all in-scope lifetimes have + // already been added to either `in_scope_lifetimes` or + // `lifetimes_to_define`. If we swapped the order of these two, + // in-band-lifetimes introduced by generics or where-clauses + // wouldn't have been added yet. + let generics = this.lower_generics_mut( + generics, + ImplTraitContext::Universal( + &mut impl_trait_defs, + this.current_hir_id_owner, + ), + ); + let res = f(this, &mut impl_trait_defs); + (generics, impl_trait_defs, res) + }) }) }); - lowered_generics.params.extend(in_band_defs); + lowered_generics.params.extend( + lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + self.lifetime_to_generic_param(span, hir_name, parent_def_id) + }) + .chain(impl_trait_defs), + ); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) @@ -1116,7 +1112,6 @@ return GenericArg::Infer(hir::InferArg { hir_id: self.lower_node_id(ty.id), span: self.lower_span(ty.span), - kind: InferKind::Type, }); } // We parse const arguments as path types as we cannot distinguish them during @@ -1188,11 +1183,7 @@ ) -> hir::Ty<'hir> { let id = self.lower_node_id(t.id); let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx); - let ty = self.ty_path(id, t.span, qpath); - if let hir::TyKind::TraitObject(..) = ty.kind { - self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global()); - } - ty + self.ty_path(id, t.span, qpath) } fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> { @@ -1258,7 +1249,7 @@ )) } TyKind::Array(ref ty, ref length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length)) + hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) } TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), TyKind::TraitObject(ref bounds, kind) => { @@ -1289,9 +1280,6 @@ lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); (bounds, lifetime_bound) }); - if kind != TraitObjectSyntax::Dyn { - self.maybe_lint_bare_trait(t.span, t.id, false); - } hir::TyKind::TraitObject(bounds, lifetime_bound, kind) } TyKind::ImplTrait(def_node_id, ref bounds) => { @@ -1379,7 +1367,7 @@ fn lower_opaque_impl_trait( &mut self, span: Span, - fn_def_id: Option, + fn_def_id: Option, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, capturable_lifetimes: Option<&FxHashSet>, @@ -1451,7 +1439,6 @@ span: lctx.lower_span(span), }, bounds: hir_bounds, - impl_trait_fn: fn_def_id, origin, }; @@ -1521,7 +1508,7 @@ fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec>)>, + mut in_band_ty_params: Option<(LocalDefId, &mut Vec>)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { @@ -1579,7 +1566,7 @@ Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id: def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(def_id), } } _ => ImplTraitContext::disallowed(), @@ -1634,7 +1621,7 @@ fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { debug!( @@ -1688,18 +1675,29 @@ // this is because the elided lifetimes from the return type // should be figured out using the ordinary elision rules, and // this desugaring achieves that. + + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); + + // Calculate all the lifetimes that should be captured + // by the opaque type. This should include all in-scope + // lifetime parameters, including those defined in-band. // - // The variable `input_lifetimes_count` tracks the number of - // lifetime parameters to the opaque type *not counting* those - // lifetimes elided in the return type. This includes those - // that are explicitly declared (`in_scope_lifetimes`) and - // those elided lifetimes we found in the arguments (current - // content of `lifetimes_to_define`). Next, we will process - // the return type, which will cause `lifetimes_to_define` to - // grow. - let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); + // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name). + + // Input lifetime like `'a` or `'1`: + let mut lifetime_params: Vec<_> = self + .in_scope_lifetimes + .iter() + .cloned() + .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name))) + .chain( + self.lifetimes_to_define + .iter() + .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))), + ) + .collect(); - let mut lifetime_params = Vec::new(); self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each @@ -1709,34 +1707,26 @@ // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = this - .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + let (lifetimes_to_define, future_bound) = + this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { + this.collect_in_band_defs(|this| { + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + }) }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define); - // Calculate all the lifetimes that should be captured - // by the opaque type. This should include all in-scope - // lifetime parameters, including those defined in-band. - // - // Note: this must be done after lowering the output type, - // as the output type may introduce new in-band lifetimes. - lifetime_params = this - .in_scope_lifetimes - .iter() - .cloned() - .map(|name| (name.ident().span, name)) - .chain(this.lifetimes_to_define.iter().cloned()) - .collect(); - - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + lifetime_params.extend( + // Output lifetime like `'_`: + lifetimes_to_define + .into_iter() + .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))), + ); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); let generic_params = - this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) + this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| { + this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1746,8 +1736,7 @@ span: this.lower_span(span), }, bounds: arena_vec![this; future_bound], - impl_trait_fn: Some(fn_def_id), - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1770,25 +1759,14 @@ // // For the "output" lifetime parameters, we just want to // generate `'_`. - let mut generic_args = Vec::with_capacity(lifetime_params.len()); - generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( - |&(span, hir_name)| { - // Input lifetime like `'a` or `'1`: + let generic_args = + self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| { GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Param(hir_name), + name, }) - }, - )); - generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| - // Output lifetime like `'_`. - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span: self.lower_span(span), - name: hir::LifetimeName::Implicit, - }))); - let generic_args = self.arena.alloc_from_iter(generic_args); + })); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the @@ -1804,7 +1782,7 @@ fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. @@ -1815,7 +1793,7 @@ // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; self.lower_ty(ty, context) } @@ -1927,7 +1905,7 @@ }); let param_name = match lt.name { hir::LifetimeName::Param(param_name) => param_name, - hir::LifetimeName::Implicit + hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), hir::LifetimeName::ImplicitObjectLifetimeDefault => { @@ -2062,6 +2040,26 @@ self.expr_block(block, AttrVec::new()) } + fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { + match c.value.kind { + ExprKind::Underscore => { + if self.sess.features_untracked().generic_arg_infer { + hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span) + } else { + feature_err( + &self.sess.parse_sess, + sym::generic_arg_infer, + c.value.span, + "using `_` for array lengths is unstable", + ) + .emit(); + hir::ArrayLen::Body(self.lower_anon_const(c)) + } + } + _ => hir::ArrayLen::Body(self.lower_anon_const(c)), + } + } + fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { self.with_new_scopes(|this| hir::AnonConst { hir_id: this.lower_node_id(c.id), @@ -2139,21 +2137,21 @@ fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None) } fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field) + self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None) } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) } fn single_pat_field( @@ -2176,8 +2174,9 @@ span: Span, lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], + hir_id: Option, ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); + let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); self.pat(span, hir::PatKind::Struct(qpath, fields, false)) } @@ -2290,7 +2289,7 @@ AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), - AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), + AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false), } } @@ -2322,11 +2321,12 @@ &'s mut self, span: Span, count: usize, + param_mode: ParamMode, ) -> impl Iterator + Captures<'a> + Captures<'s> + Captures<'hir> { - (0..count).map(move |_| self.elided_path_lifetime(span)) + (0..count).map(move |_| self.elided_path_lifetime(span, param_mode)) } - fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime { + fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime { match self.anonymous_lifetime_mode { AnonymousLifetimeMode::CreateParameter => { // We should have emitted E0726 when processing this path above @@ -2342,7 +2342,7 @@ // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.new_implicit_lifetime(span) + self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit) } } } @@ -2385,44 +2385,11 @@ r } - fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime { + fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime { hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Implicit, - } - } - - fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) { - // FIXME(davidtwco): This is a hack to detect macros which produce spans of the - // call site which do not have a macro backtrace. See #61963. - let is_macro_callsite = self - .sess - .source_map() - .span_to_snippet(span) - .map(|snippet| snippet.starts_with("#[")) - .unwrap_or(true); - if !is_macro_callsite { - if span.edition() < Edition::Edition2021 { - self.resolver.lint_buffer().buffer_lint_with_diagnostic( - BARE_TRAIT_OBJECTS, - id, - span, - "trait objects without an explicit `dyn` are deprecated", - BuiltinLintDiagnostics::BareTraitObject(span, is_global), - ) - } else { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut err = struct_span_err!(self.sess, span, E0782, "{}", msg,); - err.span_suggestion_verbose( - span.shrink_to_lo(), - label, - String::from("dyn "), - Applicability::MachineApplicable, - ); - err.emit(); - } + name: hir::LifetimeName::Implicit(missing), } } } @@ -2451,17 +2418,12 @@ } } +#[tracing::instrument(level = "debug")] fn lifetimes_from_impl_trait_bounds( opaque_ty_id: NodeId, bounds: hir::GenericBounds<'_>, lifetimes_to_include: Option<&FxHashSet>, ) -> Vec<(hir::LifetimeName, Span)> { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - bounds={:#?})", - opaque_ty_id, bounds, - ); - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. @@ -2536,7 +2498,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { let name = match lifetime.name { - hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { + hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => { if self.collect_elided_lifetimes { // Use `'_` for both implicit and underscore lifetimes in // `type Foo<'_> = impl SomeTrait<'_>;`. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/path.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/path.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/path.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/path.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,8 +7,6 @@ use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; -use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; -use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::symbol::Ident; use rustc_span::{BytePos, Span, DUMMY_SP}; @@ -231,15 +229,19 @@ if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` if !data.inputs.is_empty() { - if let Some(split) = snippet.find('(') { - let trait_name = &snippet[0..split]; - let args = &snippet[split + 1..snippet.len() - 1]; - err.span_suggestion( - data.span, - "use angle brackets instead", - format!("{}<{}>", trait_name, args), - Applicability::MaybeIncorrect, - ); + // Suggest replacing `(` and `)` with `<` and `>` + // The snippet may be missing the closing `)`, skip that case + if snippet.ends_with(')') { + if let Some(split) = snippet.find('(') { + let trait_name = &snippet[0..split]; + let args = &snippet[split + 1..snippet.len() - 1]; + err.span_suggestion( + data.span, + "use angle brackets instead", + format!("{}<{}>", trait_name, args), + Applicability::MaybeIncorrect, + ); + } } } }; @@ -270,12 +272,14 @@ let has_lifetimes = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); - if !generic_args.parenthesized && !has_lifetimes { + if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 { // Note: these spans are used for diagnostics when they can't be inferred. // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label let elided_lifetime_span = if generic_args.span.is_empty() { // If there are no brackets, use the identifier span. - segment.ident.span + // HACK: we use find_ancestor_inside to properly suggest elided spans in paths + // originating from macros, since the segment's span might be from a macro arg. + segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) } else if generic_args.is_empty() { // If there are brackets, but not generic arguments, then use the opening bracket generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)) @@ -284,67 +288,47 @@ generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo() }; generic_args.args = self - .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes) + .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode) .map(GenericArg::Lifetime) .chain(generic_args.args.into_iter()) .collect(); - if expected_lifetimes > 0 && param_mode == ParamMode::Explicit { + // In create-parameter mode we error here because we don't want to support + // deprecated impl elision in new features like impl elision and `async fn`, + // both of which work using the `CreateParameter` mode: + // + // impl Foo for std::cell::Ref // note lack of '_ + // async fn foo(_: std::cell::Ref) { ... } + if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) = + (param_mode, self.anonymous_lifetime_mode) + { let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", "); let no_non_lt_args = generic_args.args.len() == expected_lifetimes; let no_bindings = generic_args.bindings.is_empty(); - let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings { + let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings { // If there are no generic args, our suggestion can include the angle brackets. - (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion)) + (true, format!("<{}>", anon_lt_suggestion)) } else { // Otherwise we'll insert a `'_, ` right after the opening bracket. - let span = generic_args - .span - .with_lo(generic_args.span.lo() + BytePos(1)) - .shrink_to_lo(); - (false, span, format!("{}, ", anon_lt_suggestion)) + (false, format!("{}, ", anon_lt_suggestion)) }; - match self.anonymous_lifetime_mode { - // In create-parameter mode we error here because we don't want to support - // deprecated impl elision in new features like impl elision and `async fn`, - // both of which work using the `CreateParameter` mode: - // - // impl Foo for std::cell::Ref // note lack of '_ - // async fn foo(_: std::cell::Ref) { ... } - AnonymousLifetimeMode::CreateParameter => { - let mut err = struct_span_err!( - self.sess, - path_span, - E0726, - "implicit elided lifetime not allowed here" - ); - rustc_errors::add_elided_lifetime_in_path_suggestion( - &self.sess.source_map(), - &mut err, - expected_lifetimes, - path_span, - incl_angl_brckt, - insertion_sp, - suggestion, - ); - err.note("assuming a `'static` lifetime..."); - err.emit(); - } - AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.resolver.lint_buffer().buffer_lint_with_diagnostic( - ELIDED_LIFETIMES_IN_PATHS, - CRATE_NODE_ID, - path_span, - "hidden lifetime parameters in types are deprecated", - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - expected_lifetimes, - path_span, - incl_angl_brckt, - insertion_sp, - suggestion, - ), - ); - } - } + let insertion_sp = elided_lifetime_span.shrink_to_hi(); + let mut err = struct_span_err!( + self.sess, + path_span, + E0726, + "implicit elided lifetime not allowed here" + ); + rustc_errors::add_elided_lifetime_in_path_suggestion( + &self.sess.source_map(), + &mut err, + expected_lifetimes, + path_span, + incl_angl_brckt, + insertion_sp, + suggestion, + ); + err.note("assuming a `'static` lifetime..."); + err.emit(); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/pat.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/pat.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/pat.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_lowering/src/pat.rs 2022-02-23 04:07:21.000000000 +0000 @@ -24,7 +24,9 @@ let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); } - PatKind::Lit(ref e) => break hir::PatKind::Lit(self.lower_expr(e)), + PatKind::Lit(ref e) => { + break hir::PatKind::Lit(self.lower_expr_within_pat(e, false)); + } PatKind::TupleStruct(ref qself, ref path, ref pats) => { let qpath = self.lower_qpath( pattern.id, @@ -81,8 +83,8 @@ } PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { break hir::PatKind::Range( - e1.as_deref().map(|e| self.lower_expr(e)), - e2.as_deref().map(|e| self.lower_expr(e)), + e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)), + e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)), self.lower_range_end(end, e2.is_some()), ); } @@ -314,4 +316,33 @@ RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included, } } + + /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`, + /// or paths for ranges. + // + // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions? + // That means making this work: + // + // ```rust,ignore (FIXME) + // struct S; + // macro_rules! m { + // ($a:expr) => { + // let $a = S; + // } + // } + // m!(S); + // ``` + 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::Path(..) if allow_paths => {} + ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} + _ => { + self.diagnostic() + .span_err(expr.span, "arbitrary expressions aren't allowed in patterns"); + return self.arena.alloc(self.expr_err(expr.span)); + } + } + self.lower_expr(expr) + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/ast_validation.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/ast_validation.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/ast_validation.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/ast_validation.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ use rustc_span::Span; use rustc_target::spec::abi; use std::mem; -use std::ops::DerefMut; +use std::ops::{Deref, DerefMut}; const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -302,34 +302,6 @@ } } - /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`, - /// or paths for ranges. - // - // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions? - // That means making this work: - // - // ```rust,ignore (FIXME) - // struct S; - // macro_rules! m { - // ($a:expr) => { - // let $a = S; - // } - // } - // m!(S); - // ``` - fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) { - match expr.kind { - ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {} - ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} - _ => self.err_handler().span_err( - expr.span, - "arbitrary expressions aren't allowed \ - in patterns", - ), - } - } - fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) { // Check only lifetime parameters are present and that the lifetime // parameters that are present have no bounds. @@ -580,8 +552,7 @@ /// An item in `extern { ... }` cannot use non-ascii identifier. fn check_foreign_item_ascii_only(&self, ident: Ident) { - let symbol_str = ident.as_str(); - if !symbol_str.is_ascii() { + if !ident.as_str().is_ascii() { let n = 83942; self.err_handler() .struct_span_err( @@ -894,7 +865,6 @@ /// Checks that generic parameters are in the correct order, /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) fn validate_generic_param_order( - sess: &Session, handler: &rustc_errors::Handler, generics: &[GenericParam], span: Span, @@ -911,8 +881,7 @@ GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().unordered_const_ty_params(); - (ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty)) + (ParamKindOrd::Const, format!("const {}: {}", ident, ty)) } }; param_idents.push((kind, ord_kind, bounds, idx, ident)); @@ -968,14 +937,7 @@ ); err.span_suggestion( span, - &format!( - "reorder the parameters: lifetimes, {}", - if sess.features_untracked().unordered_const_ty_params() { - "then consts and types" - } else { - "then types, then consts" - } - ), + "reorder the parameters: lifetimes, then consts and types", ordered_params.clone(), Applicability::MachineApplicable, ); @@ -1342,8 +1304,6 @@ } fn visit_generics(&mut self, generics: &'a Generics) { - let cg_defaults = self.session.features_untracked().unordered_const_ty_params(); - let mut prev_param_default = None; for param in &generics.params { match param.kind { @@ -1358,12 +1318,6 @@ span, "generic parameters with a default must be trailing", ); - if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults { - err.note( - "using type defaults and const parameters \ - in the same parameter list is currently not permitted", - ); - } err.emit(); break; } @@ -1371,12 +1325,7 @@ } } - validate_generic_param_order( - self.session, - self.err_handler(), - &generics.params, - generics.span, - ); + validate_generic_param_order(self.err_handler(), &generics.params, generics.span); for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(ref predicate) = *predicate { @@ -1449,25 +1398,6 @@ visit::walk_param_bound(self, bound) } - fn visit_pat(&mut self, pat: &'a Pat) { - match &pat.kind { - PatKind::Lit(expr) => { - self.check_expr_within_pat(expr, false); - } - PatKind::Range(start, end, _) => { - if let Some(expr) = start { - self.check_expr_within_pat(expr, true); - } - if let Some(expr) = end { - self.check_expr_within_pat(expr, true); - } - } - _ => {} - } - - visit::walk_pat(self, pat) - } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); visit::walk_poly_trait_ref(self, t, m); @@ -1714,6 +1644,53 @@ } } } + // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. + if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { + if let [potential_param, potential_assoc] = &full_path.segments[..] { + for param in &generics.params { + if param.ident == potential_param.ident { + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound + { + if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { + let assoc = pprust::path_to_string(&ast::Path::from_ident( + potential_assoc.ident, + )); + let ty = pprust::ty_to_string(&predicate.rhs_ty); + let (args, span) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + continue; + }; + ( + format!(", {} = {}", assoc, ty), + arg.span().shrink_to_hi(), + ) + } + _ => continue, + }, + None => ( + format!("<{} = {}>", assoc, ty), + trait_segment.span().shrink_to_hi(), + ), + }; + err.multipart_suggestion( + &format!( + "if `{}::{}` is an associated type you're trying to set, \ + use the associated type binding syntax", + trait_segment.ident, potential_assoc.ident, + ), + vec![(span, args), (predicate.span, String::new())], + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } + } err.note( "see issue #20041 for more information", ); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/feature_gate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/feature_gate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/feature_gate.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/feature_gate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -61,7 +61,7 @@ fn check_abi(&self, abi: ast::StrLit) { let ast::StrLit { symbol_unescaped, span, .. } = abi; - match &*symbol_unescaped.as_str() { + match symbol_unescaped.as_str() { // Stable "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" | "system" => {} @@ -347,7 +347,7 @@ if let Some(modifiers) = nested_meta.value_str() { for modifier in modifiers.as_str().split(',') { - if let Some(modifier) = modifier.strip_prefix(&['+', '-'][..]) { + if let Some(modifier) = modifier.strip_prefix(&['+', '-']) { macro_rules! gate_modifier { ($($name:literal => $feature:ident)*) => { $(if modifier == $name { let msg = concat!("`#[link(modifiers=\"", $name, "\")]` is unstable"); @@ -383,7 +383,7 @@ } ast::ItemKind::Fn(..) => { - if self.sess.contains_name(&i.attrs[..], sym::start) { + if self.sess.contains_name(&i.attrs, sym::start) { gate_feature_post!( &self, start, @@ -396,7 +396,7 @@ } ast::ItemKind::Struct(..) => { - for attr in self.sess.filter_by_name(&i.attrs[..], sym::repr) { + for attr in self.sess.filter_by_name(&i.attrs, sym::repr) { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.has_name(sym::simd) { gate_feature_post!( @@ -724,15 +724,6 @@ gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); - gate_all!( - const_generics_defaults, - "default values for const generic parameters are experimental" - ); - if sess.parse_sess.span_diagnostic.err_count() == 0 { - // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is - // involved, so we only emit errors where there are no other parsing errors. - gate_all!(destructuring_assignment, "destructuring assignments are unstable"); - } // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_passes/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,6 +6,7 @@ #![feature(iter_is_partitioned)] #![feature(box_patterns)] +#![feature(let_else)] #![recursion_limit = "256"] pub mod ast_validation; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/helpers.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/helpers.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/helpers.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/helpers.rs 2022-02-23 04:07:21.000000000 +0000 @@ -35,4 +35,14 @@ self.word(w); self.nbsp() } + + // Synthesizes a comment that was not textually present in the original + // source file. + pub fn synth_comment(&mut self, text: impl Into>) { + self.word("/*"); + self.space(); + self.word(text); + self.space(); + self.word("*/") + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -73,5 +73,14 @@ } pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { - State::new().to_string(f) + State::to_string(f) +} + +pub fn crate_to_string_for_macros(krate: &ast::Crate) -> String { + State::to_string(|s| { + s.print_inner_attributes(&krate.attrs); + for item in &krate.items { + s.print_item(item); + } + }) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/state.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/state.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/state.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ast_pretty/src/pprust/state.rs 2022-02-23 04:07:21.000000000 +0000 @@ -204,14 +204,14 @@ }; if let Some(suffix) = suffix { - out.push_str(&suffix.as_str()) + out.push_str(suffix.as_str()) } out } fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String { - format!("{}{}", State::new().to_string(|s| s.print_visibility(vis)), s) + format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s) } impl std::ops::Deref for State<'_> { @@ -263,14 +263,17 @@ self.strsep(",", false, b, elts, op) } - fn maybe_print_comment(&mut self, pos: BytePos) { + fn maybe_print_comment(&mut self, pos: BytePos) -> bool { + let mut has_comment = false; while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { + has_comment = true; self.print_comment(cmnt); } else { break; } } + has_comment } fn print_comment(&mut self, cmnt: &Comment) { @@ -346,6 +349,25 @@ self.comments().as_mut().and_then(|c| c.next()) } + fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option) { + if let Some(cmnts) = self.comments() { + if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { + self.print_comment(&cmnt); + } + } + } + + fn print_remaining_comments(&mut self) { + // If there aren't any remaining comments, then we need to manually + // make sure there is a line break at the end. + if self.next_comment().is_none() { + self.hardbreak(); + } + while let Some(ref cmnt) = self.next_comment() { + self.print_comment(cmnt) + } + } + fn print_literal(&mut self, lit: &ast::Lit) { self.maybe_print_comment(lit.span.lo()); self.word(lit.token.to_string()) @@ -362,26 +384,26 @@ } fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { - self.print_string(&sym.as_str(), style); + self.print_string(sym.as_str(), style); } - fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } - fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) } - fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) { + fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) } - fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) } - fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) { + fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) } @@ -391,20 +413,21 @@ kind: ast::AttrStyle, is_inline: bool, trailing_hardbreak: bool, - ) { - let mut count = 0; + ) -> bool { + let mut printed = false; for attr in attrs { if attr.style == kind { self.print_attribute_inline(attr, is_inline); if is_inline { self.nbsp(); } - count += 1; + printed = true; } } - if count > 0 && trailing_hardbreak && !is_inline { + if printed && trailing_hardbreak && !is_inline { self.hardbreak_if_not_bol(); } + printed } fn print_attribute(&mut self, attr: &ast::Attribute) { @@ -477,7 +500,7 @@ ast::MetaItemKind::List(ref items) => { self.print_path(&item.path, false, 0); self.popen(); - self.commasep(Consistent, &items[..], |s, i| s.print_meta_list_item(i)); + self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i)); self.pclose(); } } @@ -570,7 +593,10 @@ self.print_tts(tts, convert_dollar_crate); self.end(); match delim { - DelimToken::Brace => self.bclose(span), + DelimToken::Brace => { + let empty = tts.is_empty(); + self.bclose(span, empty); + } _ => { let token_str = self.token_kind_to_string(&token::CloseDelim(delim)); self.word(token_str) @@ -642,17 +668,20 @@ self.end(); // Close the head-box. } - fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { - self.maybe_print_comment(span.hi()); - self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) { + let has_comment = self.maybe_print_comment(span.hi()); + if !empty || has_comment { + self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + } self.word("}"); if close_box { self.end(); // Close the outer-box. } } - fn bclose(&mut self, span: rustc_span::Span) { - self.bclose_maybe_open(span, true) + fn bclose(&mut self, span: rustc_span::Span, empty: bool) { + let close_box = true; + self.bclose_maybe_open(span, empty, close_box) } fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { @@ -764,55 +793,55 @@ } fn ty_to_string(&self, ty: &ast::Ty) -> String { - self.to_string(|s| s.print_type(ty)) + Self::to_string(|s| s.print_type(ty)) } fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { - self.to_string(|s| s.print_type_bounds("", bounds)) + Self::to_string(|s| s.print_type_bounds("", bounds)) } fn pat_to_string(&self, pat: &ast::Pat) -> String { - self.to_string(|s| s.print_pat(pat)) + Self::to_string(|s| s.print_pat(pat)) } fn expr_to_string(&self, e: &ast::Expr) -> String { - self.to_string(|s| s.print_expr(e)) + Self::to_string(|s| s.print_expr(e)) } fn tt_to_string(&self, tt: &TokenTree) -> String { - self.to_string(|s| s.print_tt(tt, false)) + Self::to_string(|s| s.print_tt(tt, false)) } fn tts_to_string(&self, tokens: &TokenStream) -> String { - self.to_string(|s| s.print_tts(tokens, false)) + Self::to_string(|s| s.print_tts(tokens, false)) } fn stmt_to_string(&self, stmt: &ast::Stmt) -> String { - self.to_string(|s| s.print_stmt(stmt)) + Self::to_string(|s| s.print_stmt(stmt)) } fn item_to_string(&self, i: &ast::Item) -> String { - self.to_string(|s| s.print_item(i)) + Self::to_string(|s| s.print_item(i)) } fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String { - self.to_string(|s| s.print_generic_params(generic_params)) + Self::to_string(|s| s.print_generic_params(generic_params)) } fn path_to_string(&self, p: &ast::Path) -> String { - self.to_string(|s| s.print_path(p, false, 0)) + Self::to_string(|s| s.print_path(p, false, 0)) } fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { - self.to_string(|s| s.print_path_segment(p, false)) + Self::to_string(|s| s.print_path_segment(p, false)) } fn vis_to_string(&self, v: &ast::Visibility) -> String { - self.to_string(|s| s.print_visibility(v)) + Self::to_string(|s| s.print_visibility(v)) } fn block_to_string(&self, blk: &ast::Block) -> String { - self.to_string(|s| { + Self::to_string(|s| { // Containing cbox, will be closed by `print_block` at `}`. s.cbox(INDENT_UNIT); // Head-ibox, will be closed by `print_block` after `{`. @@ -822,22 +851,22 @@ } fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { - self.to_string(|s| s.print_meta_list_item(li)) + Self::to_string(|s| s.print_meta_list_item(li)) } fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String { - self.to_string(|s| s.print_attr_item(ai, ai.path.span)) + Self::to_string(|s| s.print_attr_item(ai, ai.path.span)) } fn attribute_to_string(&self, attr: &ast::Attribute) -> String { - self.to_string(|s| s.print_attribute(attr)) + Self::to_string(|s| s.print_attribute(attr)) } fn param_to_string(&self, arg: &ast::Param) -> String { - self.to_string(|s| s.print_param(arg, false)) + Self::to_string(|s| s.print_param(arg, false)) } - fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String { + fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { let mut printer = State::new(); f(&mut printer); printer.s.eof() @@ -850,29 +879,29 @@ } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Ident(&ident)) } fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { if colons_before_params { - self.s.word("::") + self.word("::") } match *args { ast::GenericArgs::AngleBracketed(ref data) => { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &data.args, |s, arg| match arg { ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), }); - self.s.word(">") + self.word(">") } ast::GenericArgs::Parenthesized(ref data) => { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); - self.s.word(")"); + self.word(")"); self.print_fn_ret_ty(&data.output); } } @@ -884,16 +913,6 @@ State { s: pp::mk_printer(), comments: None, ann: &NoAnn } } - // Synthesizes a comment that was not textually present in the original source - // file. - pub fn synth_comment(&mut self, text: String) { - self.s.word("/*"); - self.s.space(); - self.s.word(text); - self.s.space(); - self.s.word("*/") - } - crate fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) where F: FnMut(&mut State<'_>, &T), @@ -907,7 +926,7 @@ op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -936,7 +955,7 @@ pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) { self.print_ident(constraint.ident); constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); - self.s.space(); + self.space(); match &constraint.kind { ast::AssocTyConstraintKind::Equality { ty } => { self.word_space("="); @@ -961,27 +980,27 @@ self.ibox(0); match ty.kind { ast::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("]"); + self.word("]"); } ast::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } ast::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } ast::TyKind::Never => { - self.s.word("!"); + self.word("!"); } ast::TyKind::Tup(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -999,39 +1018,39 @@ ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false), ast::TyKind::TraitObject(ref bounds, syntax) => { let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" }; - self.print_type_bounds(prefix, &bounds[..]); + self.print_type_bounds(prefix, &bounds); } ast::TyKind::ImplTrait(_, ref bounds) => { - self.print_type_bounds("impl", &bounds[..]); + self.print_type_bounds("impl", &bounds); } ast::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("; "); + self.word("; "); self.print_expr(&length.value); - self.s.word("]"); + self.word("]"); } ast::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_expr(&e.value); - self.s.word(")"); + self.word(")"); } ast::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } ast::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } ast::TyKind::ImplicitSelf => { - self.s.word("Self"); + self.word("Self"); } ast::TyKind::MacCall(ref m) => { self.print_mac(m); } ast::TyKind::CVarArgs => { - self.s.word("..."); + self.word("..."); } } self.end(); @@ -1069,7 +1088,7 @@ ast::ForeignItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1097,13 +1116,15 @@ self.print_ident(ident); self.word_space(":"); self.print_type(ty); - self.s.space(); + if body.is_some() { + self.space(); + } self.end(); // end the head-ibox if let Some(body) = body { self.word_space("="); self.print_expr(body); } - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } @@ -1125,11 +1146,11 @@ self.print_type_bounds(":", bounds); self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1145,19 +1166,19 @@ self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } ast::ItemKind::Use(ref tree) => { self.head(visibility_qualified(&item.vis, "use")); self.print_use_tree(tree); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1181,7 +1202,7 @@ ); } ast::ItemKind::Mod(unsafety, ref mod_kind) => { - self.head(self.to_string(|s| { + self.head(Self::to_string(|s| { s.print_visibility(&item.vis); s.print_unsafety(unsafety); s.word("mod"); @@ -1196,17 +1217,18 @@ for item in items { self.print_item(item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ModKind::Unloaded => { - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } } } ast::ItemKind::ForeignMod(ref nmod) => { - self.head(self.to_string(|s| { + self.head(Self::to_string(|s| { s.print_unsafety(nmod.unsafety); s.word("extern"); })); @@ -1216,7 +1238,8 @@ } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); - self.bclose(item.span); + let empty = item.attrs.is_empty() && nmod.items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::GlobalAsm(ref asm) => { self.head(visibility_qualified(&item.vis, "global_asm!")); @@ -1264,34 +1287,38 @@ self.print_visibility(&item.vis); self.print_defaultness(defaultness); self.print_unsafety(unsafety); - self.word_nbsp("impl"); - self.print_constness(constness); + self.word("impl"); - if !generics.params.is_empty() { + if generics.params.is_empty() { + self.nbsp(); + } else { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } + self.print_constness(constness); + if let ast::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = *of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(&item.attrs); for impl_item in items { self.print_assoc_item(impl_item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::Trait(box ast::Trait { is_auto, @@ -1311,22 +1338,23 @@ let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { real_bounds.push(b.clone()); } } - self.print_type_bounds(":", &real_bounds[..]); + self.print_type_bounds(":", &real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); self.print_inner_attributes(&item.attrs); for trait_item in items { self.print_assoc_item(trait_item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::TraitAlias(ref generics, ref bounds) => { self.head(""); @@ -1338,7 +1366,7 @@ // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -1346,14 +1374,14 @@ } } self.nbsp(); - self.print_type_bounds("=", &real_bounds[..]); + self.print_type_bounds("=", &real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } ast::ItemKind::MacCall(ref mac) => { self.print_mac(mac); if mac.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } ast::ItemKind::MacroDef(ref macro_def) => { @@ -1371,7 +1399,7 @@ fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -1394,7 +1422,7 @@ self.print_ident(ident); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -1406,11 +1434,12 @@ self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } - self.bclose(span) + let empty = variants.is_empty(); + self.bclose(span, empty) } crate fn print_visibility(&mut self, vis: &ast::Visibility) { @@ -1421,7 +1450,7 @@ ast::CrateSugar::JustCrate => self.word_nbsp("crate"), }, ast::VisibilityKind::Restricted { ref path, .. } => { - let path = self.to_string(|s| s.print_path(path, false, 0)); + let path = Self::to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { self.word_nbsp(format!("pub({})", path)) } else { @@ -1441,20 +1470,24 @@ crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) { self.nbsp(); self.bopen(); - self.hardbreak_if_not_bol(); - for field in fields { + let empty = fields.is_empty(); + if !empty { self.hardbreak_if_not_bol(); - self.maybe_print_comment(field.span.lo()); - self.print_outer_attributes(&field.attrs); - self.print_visibility(&field.vis); - self.print_ident(field.ident.unwrap()); - self.word_nbsp(":"); - self.print_type(&field.ty); - self.s.word(","); + + for field in fields { + self.hardbreak_if_not_bol(); + self.maybe_print_comment(field.span.lo()); + self.print_outer_attributes(&field.attrs); + self.print_visibility(&field.vis); + self.print_ident(field.ident.unwrap()); + self.word_nbsp(":"); + self.print_type(&field.ty); + self.word(","); + } } - self.bclose(span) + self.bclose(span, empty); } crate fn print_struct( @@ -1481,7 +1514,7 @@ } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end(); // Close the outer-box. @@ -1499,7 +1532,7 @@ let generics = ast::Generics::default(); self.print_struct(&v.data, &generics, v.ident, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&d.value) } @@ -1531,7 +1564,7 @@ ast::AssocItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1557,11 +1590,11 @@ if let Some(els) = els { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); - self.s.word(" else "); + self.word(" else "); self.print_block(els); } } - self.s.word(";"); + self.word(";"); self.end(); // `let` ibox } ast::StmtKind::Item(ref item) => self.print_item(item), @@ -1569,24 +1602,24 @@ self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); if classify::expr_requires_semi_to_be_stmt(expr) { - self.s.word(";"); + self.word(";"); } } ast::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); - self.s.word(";"); + self.word(";"); } ast::StmtKind::Empty => { self.space_if_not_bol(); - self.s.word(";"); + self.word(";"); } ast::StmtKind::MacCall(ref mac) => { self.space_if_not_bol(); self.print_outer_attributes(&mac.attrs); self.print_mac(&mac.mac); if mac.style == ast::MacStmtStyle::Semicolon { - self.s.word(";"); + self.word(";"); } } } @@ -1619,7 +1652,7 @@ self.ann.pre(self, AnnNode::Block(blk)); self.bopen(); - self.print_inner_attributes(attrs); + let has_attrs = self.print_inner_attributes(attrs); for (i, st) in blk.stmts.iter().enumerate() { match st.kind { @@ -1633,15 +1666,16 @@ } } - self.bclose_maybe_open(blk.span, close_box); + let empty = !has_attrs && blk.stmts.is_empty(); + self.bclose_maybe_open(blk.span, empty, close_box); self.ann.post(self, AnnNode::Block(blk)) } /// Print a `let pat = expr` expression. crate fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { - self.s.word("let "); + self.word("let "); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("="); let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) @@ -1654,9 +1688,9 @@ ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(i); - self.s.space(); + self.space(); self.print_block(then); self.print_else(e.as_deref()) } @@ -1664,7 +1698,7 @@ ast::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(b) } // Constraints would be great here! @@ -1678,7 +1712,7 @@ crate fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block(blk); self.print_else(elseopt) } @@ -1735,26 +1769,26 @@ fn print_expr_vec(&mut self, exprs: &[P]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end(); } fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("const"); + self.word("const"); self.print_expr(&expr.value); self.end(); } fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); self.print_expr(&count.value); - self.s.word("]"); + self.word("]"); self.end(); } @@ -1770,7 +1804,7 @@ } else { self.print_path(path, true, 0); } - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1790,26 +1824,26 @@ ast::StructRest::Base(_) | ast::StructRest::Rest(_) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); if let ast::StructRest::Base(ref expr) = *rest { self.print_expr(expr); } self.end(); } - ast::StructRest::None if !fields.is_empty() => self.s.word(","), + ast::StructRest::None if !fields.is_empty() => self.word(","), _ => {} } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[P]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1827,7 +1861,7 @@ fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); if let Some(ref args) = segment.args { self.print_generic_args(args, true); @@ -1868,13 +1902,13 @@ }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.to_string()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.s.word(ast::UnOp::to_string(op)); + self.word(ast::UnOp::to_string(op)); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1884,7 +1918,7 @@ mutability: ast::Mutability, expr: &ast::Expr, ) { - self.s.word("&"); + self.word("&"); match kind { ast::BorrowKind::Ref => self.print_mutability(mutability, false), ast::BorrowKind::Raw => { @@ -1932,10 +1966,10 @@ self.print_expr_tup(exprs); } ast::ExprKind::Call(ref func, ref args) => { - self.print_expr_call(func, &args[..]); + self.print_expr_call(func, &args); } ast::ExprKind::MethodCall(ref segment, ref args, _) => { - self.print_expr_method_call(segment, &args[..]); + self.print_expr_method_call(segment, &args); } ast::ExprKind::Binary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, lhs, rhs); @@ -1952,7 +1986,7 @@ ast::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(ty); } @@ -1975,7 +2009,7 @@ } self.head("while"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => { @@ -1985,10 +2019,10 @@ } self.head("for"); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("in"); self.print_expr_as_cond(iter); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Loop(ref blk, opt_label) => { @@ -2004,13 +2038,14 @@ self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(expr); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes_no_trailing_hardbreak(attrs); for arm in arms { self.print_arm(arm); } - self.bclose(expr.span); + let empty = attrs.is_empty() && arms.is_empty(); + self.bclose(expr.span, empty); } ast::ExprKind::Closure( capture_clause, @@ -2025,7 +2060,7 @@ self.print_capture_clause(capture_clause); self.print_fn_params_and_ret(decl, true); - self.s.space(); + self.space(); self.print_expr(body); self.end(); // need to close a box @@ -2048,7 +2083,6 @@ ast::ExprKind::Async(capture_clause, _, ref blk) => { self.word_nbsp("async"); self.print_capture_clause(capture_clause); - self.s.space(); // cbox/ibox in analogy to the `ExprKind::Block` arm above self.cbox(INDENT_UNIT); self.ibox(0); @@ -2056,33 +2090,33 @@ } ast::ExprKind::Await(ref expr) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word(".await"); + self.word(".await"); } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); - self.s.word(op.node.to_string()); + self.space(); + self.word(op.node.to_string()); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } ast::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(index); - self.s.word("]"); + self.word("]"); } ast::ExprKind::Range(ref start, ref end, limits) => { // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence @@ -2094,41 +2128,39 @@ self.print_expr_maybe_paren(e, fake_prec); } if limits == ast::RangeLimits::HalfOpen { - self.s.word(".."); + self.word(".."); } else { - self.s.word("..="); + self.word("..="); } if let Some(ref e) = *end { self.print_expr_maybe_paren(e, fake_prec); } } - ast::ExprKind::Underscore => self.s.word("_"), + ast::ExprKind::Underscore => self.word("_"), ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0), ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true), ast::ExprKind::Break(opt_label, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); if let Some(label) = opt_label { + self.space(); self.print_ident(label.ident); - self.s.space(); } if let Some(ref expr) = *opt_expr { + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); } } ast::ExprKind::Continue(opt_label) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); if let Some(label) = opt_label { + self.space(); self.print_ident(label.ident); - self.s.space() } } ast::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } @@ -2137,7 +2169,7 @@ self.print_inline_asm(a); } ast::ExprKind::LlvmInlineAsm(ref a) => { - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(a.asm, a.asm_str_style); self.word_space(":"); @@ -2155,7 +2187,7 @@ s.print_expr(&out.expr); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { @@ -2164,7 +2196,7 @@ s.print_expr(o); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.clobbers, |s, &co| { @@ -2183,7 +2215,7 @@ } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -2199,25 +2231,24 @@ self.pclose(); } ast::ExprKind::Yield(ref e) => { - self.s.word("yield"); + self.word("yield"); if let Some(ref expr) = *e { - self.s.space(); + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } ast::ExprKind::Try(ref e) => { self.print_expr_maybe_paren(e, parser::PREC_POSTFIX); - self.s.word("?") + self.word("?") } ast::ExprKind::TryBlock(ref blk) => { self.head("try"); - self.s.space(); self.print_block_with_attrs(blk, attrs) } ast::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose() } } @@ -2338,6 +2369,9 @@ if opts.contains(InlineAsmOptions::RAW) { options.push("raw"); } + if opts.contains(InlineAsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); @@ -2356,22 +2390,22 @@ } crate fn print_name(&mut self, name: Symbol) { - self.s.word(name.to_string()); + self.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) } fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) { - self.s.word("<"); + self.word("<"); self.print_type(&qself.ty); if qself.position > 0 { - self.s.space(); + self.space(); self.word_space("as"); let depth = path.segments.len() - qself.position; self.print_path(path, false, depth); } - self.s.word(">"); + self.word(">"); for item_segment in &path.segments[qself.position..] { - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); if let Some(ref args) = item_segment.args { self.print_generic_args(args, colons_before_params) @@ -2385,7 +2419,7 @@ /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Ident(binding_mode, ident, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { @@ -2399,8 +2433,8 @@ } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.space(); - self.s.word_space("@"); + self.space(); + self.word_space("@"); self.print_pat(p); } } @@ -2411,11 +2445,11 @@ self.print_path(path, true, 0); } self.popen(); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); self.pclose(); } PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p)); + self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p)); } PatKind::Path(None, ref path) => { self.print_path(path, true, 0); @@ -2430,10 +2464,14 @@ self.print_path(path, true, 0); } self.nbsp(); - self.word_space("{"); + self.word("{"); + let empty = fields.is_empty() && !etc; + if !empty { + self.space(); + } self.commasep_cmnt( Consistent, - &fields[..], + &fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { @@ -2449,27 +2487,29 @@ if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); } - self.s.space(); - self.s.word("}"); + if !empty { + self.space(); + } + self.word("}"); } PatKind::Tuple(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } PatKind::Box(ref inner) => { - self.s.word("box "); + self.word("box "); self.print_pat(inner); } PatKind::Ref(ref inner, mutbl) => { - self.s.word("&"); + self.word("&"); if mutbl == ast::Mutability::Mut { - self.s.word("mut "); + self.word("mut "); } if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) = inner.kind @@ -2485,23 +2525,22 @@ PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => { if let Some(e) = begin { self.print_expr(e); - self.s.space(); } match *end_kind { - RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."), - RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."), + RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="), + RangeEnd::Excluded => self.word(".."), } if let Some(e) = end { self.print_expr(e); } } PatKind::Slice(ref elts) => { - self.s.word("["); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); - self.s.word("]"); + self.word("["); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); + self.word("]"); } - PatKind::Rest => self.s.word(".."), + PatKind::Rest => self.word(".."), PatKind::Paren(ref inner) => { self.popen(); self.print_pat(inner); @@ -2515,18 +2554,18 @@ fn print_arm(&mut self, arm: &ast::Arm) { // Note, I have no idea why this check is necessary, but here it is. if arm.attrs.is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ibox(0); self.maybe_print_comment(arm.pat.span.lo()); self.print_outer_attributes(&arm.attrs); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref e) = arm.guard { self.word_space("if"); self.print_expr(e); - self.s.space(); + self.space(); } self.word_space("=>"); @@ -2542,13 +2581,13 @@ // If it is a user-provided unsafe block, print a comma after it. if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // Close the ibox for the pattern. self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.end(); // Close enclosing cbox. @@ -2558,17 +2597,17 @@ match explicit_self.node { SelfKind::Value(m) => { self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Region(ref lt, m) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lt); self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Explicit(ref typ, m) => { self.print_mutability(m, false); - self.s.word("self"); + self.word("self"); self.word_space(":"); self.print_type(typ) } @@ -2595,7 +2634,7 @@ self.nbsp(); self.print_block_with_attrs(body, attrs); } else { - self.s.word(";"); + self.word(";"); } } @@ -2646,7 +2685,7 @@ pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) { if !bounds.is_empty() { - self.s.word(prefix); + self.word(prefix); let mut first = true; for bound in bounds { if !(first && prefix.is_empty()) { @@ -2661,7 +2700,7 @@ match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } @@ -2682,10 +2721,10 @@ ) { self.print_lifetime(lifetime); if !bounds.is_empty() { - self.s.word(": "); + self.word(": "); for (i, bound) in bounds.iter().enumerate() { if i != 0 { - self.s.word(" + "); + self.word(" + "); } match bound { ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt), @@ -2700,7 +2739,7 @@ return; } - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &generic_params, |s, param| { s.print_outer_attributes_inline(¶m.attrs); @@ -2714,7 +2753,7 @@ s.print_ident(param.ident); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_type(default) } @@ -2722,12 +2761,12 @@ ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => { s.word_space("const"); s.print_ident(param.ident); - s.s.space(); + s.space(); s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_expr(&default.value); } @@ -2735,7 +2774,7 @@ } }); - self.s.word(">"); + self.word(">"); } crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) { @@ -2743,7 +2782,7 @@ return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2751,34 +2790,34 @@ self.word_space(","); } - match *predicate { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, - .. - }) => { - self.print_formal_generic_params(bound_generic_params); - self.print_type(bounded_ty); - self.print_type_bounds(":", bounds); - } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => { - self.print_lifetime_bounds(*lifetime, bounds); - } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.print_type(lhs_ty); - self.s.space(); - self.word_space("="); - self.print_type(rhs_ty); - } + self.print_where_predicate(predicate); + } + } + + pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) { + match predicate { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + bound_generic_params, + bounded_ty, + bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params); + self.print_type(bounded_ty); + self.print_type_bounds(":", bounds); + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + lifetime, + bounds, + .. + }) => { + self.print_lifetime_bounds(*lifetime, bounds); + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + self.print_type(lhs_ty); + self.space(); + self.word_space("="); + self.print_type(rhs_ty); } } } @@ -2788,7 +2827,7 @@ ast::UseTreeKind::Simple(rename, ..) => { self.print_path(&tree.prefix, false, 0); if let Some(rename) = rename { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(rename); } @@ -2796,21 +2835,21 @@ ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { self.print_path(&tree.prefix, false, 0); - self.s.word("::"); + self.word("::"); } - self.s.word("*"); + self.word("*"); } ast::UseTreeKind::Nested(ref items) => { if tree.prefix.segments.is_empty() { - self.s.word("{"); + self.word("{"); } else { self.print_path(&tree.prefix, false, 0); - self.s.word("::{"); + self.word("::{"); } - self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { + self.commasep(Inconsistent, &items, |this, &(ref tree, _)| { this.print_use_tree(tree) }); - self.s.word("}"); + self.word("}"); } } } @@ -2849,8 +2888,8 @@ }; if !invalid { self.print_pat(&input.pat); - self.s.word(":"); - self.s.space(); + self.word(":"); + self.space(); } self.print_type(&input.ty); } @@ -2879,10 +2918,7 @@ generic_params: &[ast::GenericParam], ) { self.ibox(INDENT_UNIT); - if !generic_params.is_empty() { - self.s.word("for"); - self.print_generic_params(generic_params); - } + self.print_formal_generic_params(generic_params); let generics = ast::Generics { params: Vec::new(), where_clause: ast::WhereClause { @@ -2897,29 +2933,6 @@ self.end(); } - crate fn maybe_print_trailing_comment( - &mut self, - span: rustc_span::Span, - next_pos: Option, - ) { - if let Some(cmnts) = self.comments() { - if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { - self.print_comment(&cmnt); - } - } - } - - crate fn print_remaining_comments(&mut self) { - // If there aren't any remaining comments, then we need to manually - // make sure there is a line break at the end. - if self.next_comment().is_none() { - self.s.hardbreak(); - } - while let Some(ref cmnt) = self.next_comment() { - self.print_comment(cmnt); - } - } - crate fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); self.print_asyncness(header.asyncness); @@ -2937,7 +2950,7 @@ } } - self.s.word("fn") + self.word("fn") } crate fn print_unsafety(&mut self, s: ast::Unsafe) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_attr/src/builtin.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_attr/src/builtin.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_attr/src/builtin.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_attr/src/builtin.rs 2022-02-23 04:07:21.000000000 +0000 @@ -236,7 +236,7 @@ // These unwraps are safe because `get` ensures the meta item // is a name/value pair string literal. - issue_num = match &*issue.unwrap().as_str() { + issue_num = match issue.unwrap().as_str() { "none" => None, issue => { let emit_diag = |msg: &str| { @@ -301,7 +301,7 @@ match (feature, reason, issue) { (Some(feature), reason, Some(_)) => { - if !rustc_lexer::is_ident(&feature.as_str()) { + if !rustc_lexer::is_ident(feature.as_str()) { handle_errors( &sess.parse_sess, attr.span, @@ -519,8 +519,10 @@ [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => { (sym, span) } - [NestedMetaItem::Literal(Lit { span, .. }) - | NestedMetaItem::MetaItem(MetaItem { span, .. })] => { + [ + NestedMetaItem::Literal(Lit { span, .. }) + | NestedMetaItem::MetaItem(MetaItem { span, .. }), + ] => { sess.span_diagnostic .struct_span_err(*span, "expected a version literal") .emit(); @@ -533,7 +535,7 @@ return false; } }; - let min_version = match parse_version(&min_version.as_str(), false) { + let min_version = match parse_version(min_version.as_str(), false) { Some(ver) => ver, None => { sess.span_diagnostic diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/borrow_set.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/borrow_set.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/borrow_set.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/borrow_set.rs 2022-02-23 04:07:21.000000000 +0000 @@ -84,7 +84,7 @@ } impl LocalsStateAtExit { - fn build( + fn build<'tcx>( locals_are_invalidated_at_exit: bool, body: &Body<'tcx>, move_data: &MoveData<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/dataflow.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/dataflow.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/dataflow.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/dataflow.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,7 +5,7 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::ResultsVisitable; -use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill}; +use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill}; use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; use std::iter; @@ -434,9 +434,7 @@ &self, _trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/def_use.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/def_use.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/def_use.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/def_use.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,7 +17,7 @@ PlaceContext::MutatingUse(MutatingUseContext::Store) | // This is potentially both a def and a use... - PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput) | // We let Call define the result in both the success and // unwind cases. This is not really correct, however it @@ -26,6 +26,7 @@ // the def in call only to the input from the success // path and not the unwind path. -nmatsakis PlaceContext::MutatingUse(MutatingUseContext::Call) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Yield) | // Storage live and storage dead aren't proper defines, but we can ignore diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ Other, } -impl UniverseInfo<'tcx> { +impl<'tcx> UniverseInfo<'tcx> { crate fn other() -> UniverseInfo<'tcx> { UniverseInfo(UniverseInfoInner::Other) } @@ -191,7 +191,7 @@ base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); @@ -231,7 +231,7 @@ base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> +impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> where T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, { @@ -291,7 +291,7 @@ base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. @@ -368,6 +368,7 @@ error_region, cause.clone(), placeholder_region, + vec![], ), ), (Some(error_region), _) => NiceRegionError::new( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs 2022-02-23 04:07:21.000000000 +0000 @@ -15,16 +15,18 @@ use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt; +use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; +use crate::diagnostics::find_all_local_uses; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, }; use super::{ - explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName, - RegionNameSource, UseSpans, + explain_borrow::{BorrowExplanation, LaterUseKind}, + FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans, }; #[derive(Debug)] @@ -414,7 +416,7 @@ tcx, generics, &mut err, - ¶m.name.as_str(), + param.name.as_str(), "Copy", None, ); @@ -768,9 +770,92 @@ Some((issued_span, span)), ); + self.suggest_using_local_if_applicable( + &mut err, + location, + (place, span), + gen_borrow_kind, + issued_borrow, + explanation, + ); + err } + #[instrument(level = "debug", skip(self, err))] + fn suggest_using_local_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + location: Location, + (place, span): (Place<'tcx>, Span), + gen_borrow_kind: BorrowKind, + issued_borrow: &BorrowData<'tcx>, + explanation: BorrowExplanation, + ) { + let used_in_call = + matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _)); + if !used_in_call { + debug!("not later used in call"); + return; + } + + let outer_call_loc = + if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location { + loc + } else { + issued_borrow.reserve_location + }; + let outer_call_stmt = self.body.stmt_at(outer_call_loc); + + let inner_param_location = location; + let Some(inner_param_stmt) = self.body.stmt_at(inner_param_location).left() else { + debug!("`inner_param_location` {:?} is not for a statement", inner_param_location); + return; + }; + let Some(&inner_param) = inner_param_stmt.kind.as_assign().map(|(p, _)| p) else { + debug!( + "`inner_param_location` {:?} is not for an assignment: {:?}", + inner_param_location, inner_param_stmt + ); + return; + }; + let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local); + let Some((inner_call_loc,inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| { + let Either::Right(term) = self.body.stmt_at(loc) else { + debug!("{:?} is a statement, so it can't be a call", loc); + return None; + }; + let TerminatorKind::Call { args, .. } = &term.kind else { + debug!("not a call: {:?}", term); + return None; + }; + debug!("checking call args for uses of inner_param: {:?}", args); + if args.contains(&Operand::Move(inner_param)) { + Some((loc,term)) + } else { + None + } + }) else { + debug!("no uses of inner_param found as a by-move call arg"); + return; + }; + debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc); + + let inner_call_span = inner_call_term.source_info.span; + let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span; + if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) { + // FIXME: This stops the suggestion in some cases where it should be emitted. + // Fix the spans for those cases so it's emitted correctly. + debug!( + "outer span {:?} does not strictly contain inner span {:?}", + outer_call_span, inner_call_span + ); + return; + } + err.span_help(inner_call_span, "try adding a local storing this argument..."); + err.span_help(outer_call_span, "...and then using that local as the argument to this call"); + } + fn suggest_split_at_mut_if_applicable( &self, err: &mut DiagnosticBuilder<'_>, @@ -977,9 +1062,7 @@ Some(ref name), BorrowExplanation::MustBeValidFor { category: - category - @ - (ConstraintCategory::Return(_) + category @ (ConstraintCategory::Return(_) | ConstraintCategory::CallArgument | ConstraintCategory::OpaqueType), from_closure: false, @@ -1515,8 +1598,8 @@ location: Location, mpi: MovePathIndex, ) -> (Vec, Vec) { - fn predecessor_locations( - body: &'a mir::Body<'tcx>, + fn predecessor_locations<'a>( + body: &'a mir::Body<'_>, location: Location, ) -> impl Iterator + 'a { if location.statement_index == 0 { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,26 @@ +use std::collections::BTreeSet; + +use rustc_middle::mir::visit::{PlaceContext, Visitor}; +use rustc_middle::mir::{Body, Local, Location}; + +/// Find all uses of (including assignments to) a [`Local`]. +/// +/// Uses `BTreeSet` so output is deterministic. +pub(super) fn find<'tcx>(body: &Body<'tcx>, local: Local) -> BTreeSet { + let mut visitor = AllLocalUsesVisitor { for_local: local, uses: BTreeSet::default() }; + visitor.visit_body(body); + visitor.uses +} + +struct AllLocalUsesVisitor { + for_local: Local, + uses: BTreeSet, +} + +impl<'tcx> Visitor<'tcx> for AllLocalUsesVisitor { + fn visit_local(&mut self, local: &Local, _context: PlaceContext, location: Location) { + if *local == self.for_local { + self.uses.insert(location); + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -19,6 +19,7 @@ use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; +mod find_all_local_uses; mod find_use; mod outlives_suggestion; mod region_name; @@ -205,7 +206,7 @@ { let local_info = &self.body.local_decls[local].local_info; if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { - buf.push_str(&self.infcx.tcx.item_name(def_id).as_str()); + buf.push_str(self.infcx.tcx.item_name(def_id).as_str()); } else { unreachable!(); } @@ -317,7 +318,7 @@ let decl = &self.body.local_decls[local]; match self.local_names[local] { Some(name) if !decl.from_compiler_desugaring() => { - buf.push_str(&name.as_str()); + buf.push_str(name.as_str()); Ok(()) } _ => Err(()), @@ -408,7 +409,7 @@ /// Add a note that a type does not implement `Copy` pub(super) fn note_type_does_not_implement_copy( &self, - err: &mut DiagnosticBuilder<'a>, + err: &mut DiagnosticBuilder<'_>, place_desc: &str, ty: Ty<'tcx>, span: Option, @@ -732,21 +733,19 @@ OverloadedIndex(Ty<'tcx>), } -impl BorrowedContentSource<'tcx> { +impl<'tcx> BorrowedContentSource<'tcx> { pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String { match *self { BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(), BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(), BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(), - BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { - "an `Rc`".to_string() - } - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { - "an `Arc`".to_string() - } - _ => format!("dereference of `{}`", ty), - }, + BorrowedContentSource::OverloadedDeref(ty) => ty + .ty_adt_def() + .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? { + name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)), + _ => None, + }) + .unwrap_or_else(|| format!("dereference of `{}`", ty)), BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty), } } @@ -770,15 +769,13 @@ BorrowedContentSource::DerefMutableRef => { bug!("describe_for_immutable_place: DerefMutableRef isn't immutable") } - BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { - "an `Rc`".to_string() - } - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { - "an `Arc`".to_string() - } - _ => format!("a dereference of `{}`", ty), - }, + BorrowedContentSource::OverloadedDeref(ty) => ty + .ty_adt_def() + .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? { + name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)), + _ => None, + }) + .unwrap_or_else(|| format!("dereference of `{}`", ty)), BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty), } } @@ -960,8 +957,7 @@ _ => None, }); let is_option_or_result = parent_self_ty.map_or(false, |def_id| { - tcx.is_diagnostic_item(sym::Option, def_id) - || tcx.is_diagnostic_item(sym::Result, def_id) + matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } }); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs 2022-02-23 04:07:21.000000000 +0000 @@ -165,10 +165,13 @@ PlaceRef { local: _, projection: - [.., ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::Downcast(..)], + [ + .., + ProjectionElem::Index(_) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(..), + ], } => bug!("Unexpected immutable place."), } @@ -217,19 +220,24 @@ PlaceRef { local, projection: - [proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref], + [ + proj_base @ .., + ProjectionElem::Deref, + ProjectionElem::Field(field, _), + ProjectionElem::Deref, + ], } => { err.span_label(span, format!("cannot {ACT}", ACT = act)); - if let Some((span, message)) = annotate_struct_field( + if let Some(span) = get_mut_span_in_struct_field( self.infcx.tcx, Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, field, ) { - err.span_suggestion( + err.span_suggestion_verbose( span, "consider changing this to be mutable", - message, + " mut ".into(), Applicability::MaybeIncorrect, ); } @@ -739,7 +747,7 @@ HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option { + fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option { match hir_map.find(id) { Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { @@ -763,11 +771,14 @@ kind: Call( _, - [Expr { - kind: MethodCall(path_segment, ..), - hir_id, - .. - }, ..], + [ + Expr { + kind: MethodCall(path_segment, ..), + hir_id, + .. + }, + .., + ], ), .. }, @@ -1048,18 +1059,18 @@ ty.is_closure() || ty.is_generator() } -/// Adds a suggestion to a struct definition given a field access to a local. -/// This function expects the local to be a reference to a struct in order to produce a suggestion. +/// Given a field that needs to be mutable, returns a span where the " mut " could go. +/// This function expects the local to be a reference to a struct in order to produce a span. /// /// ```text -/// LL | s: &'a String -/// | ---------- use `&'a mut String` here to make mutable +/// LL | s: &'a String +/// | ^^^ returns a span taking up the space here /// ``` -fn annotate_struct_field( +fn get_mut_span_in_struct_field<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, field: &mir::Field, -) -> Option<(Span, String)> { +) -> Option { // Expect our local to be a reference to a struct of some kind. if let ty::Ref(_, ty, _) = ty.kind() { if let ty::Adt(def, _) = ty.kind() { @@ -1070,25 +1081,10 @@ // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. if let hir::Node::Field(field) = node { - if let hir::TyKind::Rptr( - lifetime, - hir::MutTy { mutbl: hir::Mutability::Not, ref ty }, - ) = field.ty.kind + if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = + field.ty.kind { - // Get the snippets in two parts - the named lifetime (if there is one) and - // type being referenced, that way we can reconstruct the snippet without loss - // of detail. - let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?; - let lifetime_snippet = if !lifetime.is_elided() { - format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?) - } else { - String::new() - }; - - return Some(( - field.ty.span, - format!("&{}mut {}", lifetime_snippet, &*type_snippet,), - )); + return Some(lifetime.span.between(ty.span)); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_errors.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_errors.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_errors.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_errors.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, }; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; -use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -334,13 +334,43 @@ match variance_info { ty::VarianceDiagInfo::None => {} - ty::VarianceDiagInfo::Mut { kind, ty } => { - let kind_name = match kind { - ty::VarianceDiagMutKind::Ref => "reference", - ty::VarianceDiagMutKind::RawPtr => "pointer", + ty::VarianceDiagInfo::Invariant { ty, param_index } => { + let (desc, note) = match ty.kind() { + ty::RawPtr(ty_mut) => { + assert_eq!(ty_mut.mutbl, rustc_hir::Mutability::Mut); + ( + format!("a mutable pointer to {}", ty_mut.ty), + "mutable pointers are invariant over their type parameter".to_string(), + ) + } + ty::Ref(_, inner_ty, mutbl) => { + assert_eq!(*mutbl, rustc_hir::Mutability::Mut); + ( + format!("a mutable reference to {}", inner_ty), + "mutable references are invariant over their type parameter" + .to_string(), + ) + } + ty::Adt(adt, substs) => { + let generic_arg = substs[param_index as usize]; + let identity_substs = + InternalSubsts::identity_for_item(self.infcx.tcx, adt.did); + let base_ty = self.infcx.tcx.mk_adt(adt, identity_substs); + let base_generic_arg = identity_substs[param_index as usize]; + let adt_desc = adt.descr(); + + let desc = format!( + "the type {ty}, which makes the generic argument {generic_arg} invariant" + ); + let note = format!( + "the {adt_desc} {base_ty} is invariant over the parameter {base_generic_arg}" + ); + (desc, note) + } + _ => panic!("Unexpected type {:?}", ty), }; - diag.note(&format!("requirement occurs because of a mutable {kind_name} to {ty}",)); - diag.note(&format!("mutable {kind_name}s are invariant over their type parameter")); + diag.note(&format!("requirement occurs because of {desc}",)); + diag.note(¬e); diag.help("see for more information about variance"); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_name.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_name.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_name.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/diagnostics/region_name.rs 2022-02-23 04:07:21.000000000 +0000 @@ -584,7 +584,7 @@ Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) } - hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => { + hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => { // In this case, the user left off the lifetime; so // they wrote something like: // @@ -769,20 +769,24 @@ let opaque_ty = hir.item(id); if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: - [hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _, - _, - hir::GenericArgs { - bindings: - [hir::TypeBinding { - ident: Ident { name: sym::Output, .. }, - kind: hir::TypeBindingKind::Equality { ty }, - .. - }], - .. - }, - )], + [ + hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _, + _, + hir::GenericArgs { + bindings: + [ + hir::TypeBinding { + ident: Ident { name: sym::Output, .. }, + kind: hir::TypeBindingKind::Equality { ty }, + .. + }, + ], + .. + }, + ), + ], .. }) = opaque_ty.kind { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/invalidation.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/invalidation.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/invalidation.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/invalidation.rs 2022-02-23 04:07:21.000000000 +0000 @@ -199,6 +199,7 @@ options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,9 +3,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] @@ -792,6 +789,7 @@ options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { @@ -1396,10 +1394,6 @@ Rvalue::NullaryOp(_op, _ty) => { // nullary ops take no dynamic input; no borrowck effect. - // - // FIXME: is above actually true? Do we want to track - // the fact that uninitialized data can be created via - // `NullOp::Box`? } Rvalue::Aggregate(ref aggregate_kind, ref operands) => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/member_constraints.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/member_constraints.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/member_constraints.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/member_constraints.rs 2022-02-23 04:07:21.000000000 +0000 @@ -53,7 +53,7 @@ } } -impl Default for MemberConstraintSet<'tcx, ty::RegionVid> { +impl Default for MemberConstraintSet<'_, ty::RegionVid> { fn default() -> Self { Self { first_constraints: Default::default(), @@ -97,7 +97,7 @@ } } -impl MemberConstraintSet<'tcx, R1> +impl<'tcx, R1> MemberConstraintSet<'tcx, R1> where R1: Copy + Hash + Eq, { @@ -140,7 +140,7 @@ } } -impl MemberConstraintSet<'tcx, R> +impl MemberConstraintSet<'_, R> where R: Copy + Hash + Eq, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/path_utils.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/path_utils.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/path_utils.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/path_utils.rs 2022-02-23 04:07:21.000000000 +0000 @@ -141,7 +141,7 @@ /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. -pub(crate) fn is_upvar_field_projection( +pub(crate) fn is_upvar_field_projection<'tcx>( tcx: TyCtxt<'tcx>, upvars: &[Upvar<'tcx>], place_ref: PlaceRef<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/opaque_types.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/opaque_types.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/opaque_types.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/opaque_types.rs 2022-02-23 04:07:21.000000000 +0000 @@ -173,7 +173,7 @@ // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, // Check these OpaqueTyOrigin::TyAlias => {} } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/values.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/values.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/values.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/region_infer/values.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; -use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; +use rustc_index::bit_set::SparseBitMatrix; +use rustc_index::interval::IntervalSet; +use rustc_index::interval::SparseIntervalMatrix; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; @@ -110,11 +112,11 @@ PlaceholderRegion(ty::PlaceholderRegion), } -/// When we initially compute liveness, we use a bit matrix storing -/// points for each region-vid. +/// When we initially compute liveness, we use an interval matrix storing +/// liveness ranges for each region-vid. crate struct LivenessValues { elements: Rc, - points: SparseBitMatrix, + points: SparseIntervalMatrix, } impl LivenessValues { @@ -122,7 +124,7 @@ /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. crate fn new(elements: Rc) -> Self { - Self { points: SparseBitMatrix::new(elements.num_points), elements } + Self { points: SparseIntervalMatrix::new(elements.num_points), elements } } /// Iterate through each region that has a value in this set. @@ -140,7 +142,7 @@ /// Adds all the elements in the given bit array into the given /// region. Returns whether any of them are newly added. - crate fn add_elements(&mut self, row: N, locations: &HybridBitSet) -> bool { + crate fn add_elements(&mut self, row: N, locations: &IntervalSet) -> bool { debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); self.points.union_row(row, locations) } @@ -153,7 +155,7 @@ /// Returns `true` if the region `r` contains the given element. crate fn contains(&self, row: N, location: Location) -> bool { let index = self.elements.point_from_location(location); - self.points.contains(row, index) + self.points.row(row).map_or(false, |r| r.contains(index)) } /// Returns an iterator of all the elements contained by the region `r` @@ -221,7 +223,7 @@ crate struct RegionValues { elements: Rc, placeholder_indices: Rc, - points: SparseBitMatrix, + points: SparseIntervalMatrix, free_regions: SparseBitMatrix, /// Placeholders represent bound regions -- so something like `'a` @@ -241,7 +243,7 @@ let num_placeholders = placeholder_indices.len(); Self { elements: elements.clone(), - points: SparseBitMatrix::new(elements.num_points), + points: SparseIntervalMatrix::new(elements.num_points), placeholder_indices: placeholder_indices.clone(), free_regions: SparseBitMatrix::new(num_universal_regions), placeholders: SparseBitMatrix::new(num_placeholders), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/renumber.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/renumber.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/renumber.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/renumber.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_middle::mir::visit::{MutVisitor, TyContext}; -use rustc_middle::mir::{Body, Location, PlaceElem, Promoted}; +use rustc_middle::mir::{Body, Location, Promoted}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -62,22 +62,6 @@ debug!(?ty); } - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - if let PlaceElem::Field(field, ty) = elem { - let new_ty = self.renumber_regions(ty); - - if new_ty != ty { - return Some(PlaceElem::Field(field, new_ty)); - } - } - - None - } - #[instrument(skip(self), level = "debug")] fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { *substs = self.renumber_regions(*substs); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,6 +6,7 @@ use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::DUMMY_SP; @@ -95,11 +96,23 @@ self.add_outlives(r1_vid, r2_vid); } - GenericArgKind::Type(t1) => { + GenericArgKind::Type(mut t1) => { // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + // Placeholder regions need to be converted now because it may + // create new region variables, which can't be done later when + // verifying these bounds. + if t1.has_placeholders() { + t1 = tcx.fold_regions(&t1, &mut false, |r, _| match *r { + ty::RegionKind::RePlaceholder(placeholder) => { + self.constraints.placeholder_region(self.infcx, placeholder) + } + _ => r, + }); + } + TypeOutlives::new( &mut *self, tcx, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/free_region_relations.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/free_region_relations.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/free_region_relations.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/free_region_relations.rs 2022-02-23 04:07:21.000000000 +0000 @@ -58,7 +58,7 @@ crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } -crate fn create( +crate fn create<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, implicit_region_bound: Option>, @@ -81,7 +81,7 @@ .create() } -impl UniversalRegionRelations<'tcx> { +impl UniversalRegionRelations<'_> { /// Records in the `outlives_relation` (and /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the /// builder below. @@ -110,7 +110,7 @@ /// outlives `fr` and (b) is not local. /// /// (*) If there are multiple competing choices, we return all of them. - crate fn non_local_upper_bounds(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { + crate fn non_local_upper_bounds<'a>(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { debug!("non_local_upper_bound(fr={:?})", fr); let res = self.non_local_bounds(&self.inverse_outlives, fr); assert!(!res.is_empty(), "can't find an upper bound!?"); @@ -232,7 +232,7 @@ region_bound_pairs: RegionBoundPairs<'tcx>, } -impl UniversalRegionRelationsBuilder<'cx, 'tcx> { +impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { crate fn create(mut self) -> CreateResult<'tcx> { let unnormalized_input_output_tys = self .universal_regions diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/input_output.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/input_output.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/input_output.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/input_output.rs 2022-02-23 04:07:21.000000000 +0000 @@ -117,9 +117,29 @@ } } - assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some()); - if let Some(mir_yield_ty) = body.yield_ty() { - let ur_yield_ty = universal_regions.yield_ty.unwrap(); + debug!( + "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}", + body.yield_ty(), + universal_regions.yield_ty + ); + + // We will not have a universal_regions.yield_ty if we yield (by accident) + // outside of a generator and return an `impl Trait`, so emit a delay_span_bug + // because we don't want to panic in an assert here if we've already got errors. + if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() { + self.tcx().sess.delay_span_bug( + body.span, + &format!( + "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})", + body.yield_ty(), + universal_regions.yield_ty, + ), + ); + } + + if let (Some(mir_yield_ty), Some(ur_yield_ty)) = + (body.yield_ty(), universal_regions.yield_ty) + { let yield_span = body.local_decls[RETURN_PLACE].source_info.span; self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -152,7 +152,7 @@ } } -impl Visitor<'tcx> for LocalUseMapBuild<'_> { +impl Visitor<'_> for LocalUseMapBuild<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { if self.locals_with_use_data[local] { match def_use::categorize(context) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -74,7 +74,7 @@ // to compute whether a variable `X` is live if that variable contains // some region `R` in its type where `R` is not known to outlive a free // region (i.e., where `R` may be valid for just a subset of the fn body). -fn compute_live_locals( +fn compute_live_locals<'tcx>( tcx: TyCtxt<'tcx>, free_regions: &FxHashSet, body: &Body<'tcx>, @@ -104,7 +104,7 @@ /// regions. For these regions, we do not need to compute /// liveness, since the outlives constraints will ensure that they /// are live over the whole fn body anyhow. -fn regions_that_outlive_free_regions( +fn regions_that_outlive_free_regions<'tcx>( num_region_vars: usize, universal_regions: &UniversalRegions<'tcx>, constraint_set: &OutlivesConstraintSet<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs 2022-02-23 04:07:21.000000000 +0000 @@ -53,7 +53,7 @@ } } -impl Visitor<'tcx> for UseFactsExtractor<'_> { +impl Visitor<'_> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match def_use::categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -63,7 +63,7 @@ } } - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) { self.super_place(place, context, location); match context { PlaceContext::NonMutatingUse(_) => { @@ -82,7 +82,7 @@ } } -pub(super) fn populate_access_facts( +pub(super) fn populate_access_facts<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, location_table: &LocationTable, @@ -123,7 +123,7 @@ // For every potentially drop()-touched region `region` in `local`'s type // (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. -pub(super) fn add_drop_of_var_derefs_origin( +pub(super) fn add_drop_of_var_derefs_origin<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/trace.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/trace.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/trace.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/liveness/trace.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::HybridBitSet; +use rustc_index::interval::IntervalSet; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::ty::{Ty, TypeFoldable}; @@ -34,7 +35,7 @@ /// DROP-LIVE set are to the liveness sets for regions found in the /// `dropck_outlives` result of the variable's type (in particular, /// this respects `#[may_dangle]` annotations). -pub(super) fn trace( +pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, @@ -105,12 +106,12 @@ /// Points where the current variable is "use live" -- meaning /// that there is a future "full use" that may use its value. - use_live_at: HybridBitSet, + use_live_at: IntervalSet, /// Points where the current variable is "drop live" -- meaning /// that there is no future "full use" that may use its value, but /// there is a future drop. - drop_live_at: HybridBitSet, + drop_live_at: IntervalSet, /// Locations where drops may occur. drop_locations: Vec, @@ -119,14 +120,14 @@ stack: Vec, } -impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { +impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, defs: HybridBitSet::new_empty(num_points), - use_live_at: HybridBitSet::new_empty(num_points), - drop_live_at: HybridBitSet::new_empty(num_points), + use_live_at: IntervalSet::new(num_points), + drop_live_at: IntervalSet::new(num_points), drop_locations: vec![], stack: vec![], } @@ -165,7 +166,7 @@ drop_used: Vec<(Local, Location)>, live_locals: FxHashSet, ) { - let locations = HybridBitSet::new_empty(self.cx.elements.num_points()); + let locations = IntervalSet::new(self.cx.elements.num_points()); for (local, location) in drop_used { if !live_locals.contains(&local) { @@ -418,7 +419,7 @@ } } -impl LivenessContext<'_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. @@ -456,7 +457,7 @@ fn add_use_live_facts_for( &mut self, value: impl TypeFoldable<'tcx>, - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!("add_use_live_facts_for(value={:?})", value); @@ -473,7 +474,7 @@ dropped_local: Local, dropped_ty: Ty<'tcx>, drop_locations: &[Location], - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!( "add_drop_live_constraint(\ @@ -521,7 +522,7 @@ elements: &RegionValueElements, typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeFoldable<'tcx>, - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!("make_all_regions_live(value={:?})", value); debug!( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, - ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, + ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; @@ -945,7 +945,7 @@ crate type_tests: Vec>, } -impl MirTypeckRegionConstraints<'tcx> { +impl<'tcx> MirTypeckRegionConstraints<'tcx> { fn placeholder_region( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -1828,10 +1828,16 @@ self.assert_iscleanup(body, block_data, unwind, true); } } - TerminatorKind::InlineAsm { destination, .. } => { + TerminatorKind::InlineAsm { destination, cleanup, .. } => { if let Some(target) = destination { self.assert_iscleanup(body, block_data, target, is_cleanup); } + if let Some(cleanup) = cleanup { + if is_cleanup { + span_mirbug!(self, block_data, "cleanup on cleanup block") + } + self.assert_iscleanup(body, block_data, cleanup, true); + } } } } @@ -1910,7 +1916,8 @@ let tcx = self.tcx(); match *ak { - AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => { + AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => { + let def = tcx.adt_def(adt_did); let variant = &def.variants[variant_index]; let adj_field_index = active_field_index.unwrap_or(field_index); if let Some(field) = variant.fields.get(adj_field_index) { @@ -2615,8 +2622,8 @@ ); let (def_id, instantiated_predicates) = match aggregate_kind { - AggregateKind::Adt(def, _, substs, _, _) => { - (def.did, tcx.predicates_of(def.did).instantiate(tcx, substs)) + AggregateKind::Adt(adt_did, _, substs, _, _) => { + (*adt_did, tcx.predicates_of(*adt_did).instantiate(tcx, substs)) } // For closures, we have some **extra requirements** we diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/relate_tys.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/relate_tys.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/relate_tys.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_borrowck/src/type_check/relate_tys.rs 2022-02-23 04:07:21.000000000 +0000 @@ -51,7 +51,7 @@ universe_info: UniverseInfo<'tcx>, } -impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { +impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, @@ -62,7 +62,7 @@ } } -impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { +impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -15,6 +15,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } +rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,13 +8,14 @@ use rustc_parse::parser::Parser; use rustc_parse_format as parse; use rustc_session::lint; +use rustc_session::parse::ParseSess; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; -struct AsmArgs { +pub struct AsmArgs { templates: Vec>, operands: Vec<(ast::InlineAsmOperand, Span)>, named_args: FxHashMap, @@ -31,30 +32,30 @@ is_global_asm: bool, ) -> Result> { let mut p = ecx.new_parser_from_tts(tts); + let sess = &ecx.sess.parse_sess; + parse_asm_args(&mut p, sess, sp, is_global_asm) +} + +// Primarily public for rustfmt consumption. +// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm` +pub fn parse_asm_args<'a>( + p: &mut Parser<'a>, + sess: &'a ParseSess, + sp: Span, + is_global_asm: bool, +) -> Result> { + let diag = &sess.span_diagnostic; if p.token == token::Eof { - return Err(ecx.struct_span_err(sp, "requires at least a template string argument")); + return Err(diag.struct_span_err(sp, "requires at least a template string argument")); } // Detect use of the legacy llvm_asm! syntax (which used to be called asm!) if !is_global_asm && p.look_ahead(1, |t| *t == token::Colon || *t == token::ModSep) { let mut err = - ecx.struct_span_err(sp, "the legacy LLVM-style asm! syntax is no longer supported"); + diag.struct_span_err(sp, "the legacy LLVM-style asm! syntax is no longer supported"); err.note("consider migrating to the new asm! syntax specified in RFC 2873"); err.note("alternatively, switch to llvm_asm! to keep your code working as it is"); - - // Find the span of the "asm!" so that we can offer an automatic suggestion - let asm_span = sp.from_inner(InnerSpan::new(0, 4)); - if let Ok(s) = ecx.source_map().span_to_snippet(asm_span) { - if s == "asm!" { - err.span_suggestion( - asm_span, - "replace with", - "llvm_asm!".into(), - Applicability::MachineApplicable, - ); - } - } return Err(err); } @@ -74,7 +75,7 @@ if !p.eat(&token::Comma) { if allow_templates { // After a template string, we always expect *only* a comma... - let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); + let mut err = diag.struct_span_err(p.token.span, "expected token: `,`"); err.span_label(p.token.span, "expected `,`"); p.maybe_annotate_with_ascription(&mut err, false); return Err(err); @@ -89,14 +90,14 @@ // Parse clobber_abi if p.eat_keyword(sym::clobber_abi) { - parse_clobber_abi(&mut p, &mut args)?; + parse_clobber_abi(p, &mut args)?; allow_templates = false; continue; } // Parse options if p.eat_keyword(sym::options) { - parse_options(&mut p, &mut args, is_global_asm)?; + parse_options(p, &mut args, is_global_asm)?; allow_templates = false; continue; } @@ -116,25 +117,25 @@ let mut explicit_reg = false; let op = if !is_global_asm && p.eat_keyword(kw::In) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } } else if !is_global_asm && p.eat_keyword(sym::out) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: false } } else if !is_global_asm && p.eat_keyword(sym::lateout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: true } } else if !is_global_asm && p.eat_keyword(sym::inout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; @@ -146,9 +147,9 @@ ast::InlineAsmOperand::InOut { reg, expr, late: false } } } else if !is_global_asm && p.eat_keyword(sym::inlateout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; @@ -167,7 +168,7 @@ match expr.kind { ast::ExprKind::Path(..) => {} _ => { - let err = ecx + let err = diag .struct_span_err(expr.span, "argument to `sym` must be a path expression"); return Err(err); } @@ -186,7 +187,7 @@ } else { "expected operand, clobber_abi, options, or additional template string" }; - let mut err = ecx.struct_span_err(template.span, errstr); + let mut err = diag.struct_span_err(template.span, errstr); err.span_label(template.span, errstr); return Err(err); } @@ -206,31 +207,31 @@ // clobber_abi/options. We do this at the end once we have the full span // of the argument available. if !args.options_spans.is_empty() { - ecx.struct_span_err(span, "arguments are not allowed after options") + diag.struct_span_err(span, "arguments are not allowed after options") .span_labels(args.options_spans.clone(), "previous options") .span_label(span, "argument") .emit(); } else if let Some((_, abi_span)) = args.clobber_abis.last() { - ecx.struct_span_err(span, "arguments are not allowed after clobber_abi") + diag.struct_span_err(span, "arguments are not allowed after clobber_abi") .span_label(*abi_span, "clobber_abi") .span_label(span, "argument") .emit(); } if explicit_reg { if name.is_some() { - ecx.struct_span_err(span, "explicit register arguments cannot have names").emit(); + diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); } args.reg_args.insert(slot); } else if let Some(name) = name { if let Some(&prev) = args.named_args.get(&name) { - ecx.struct_span_err(span, &format!("duplicate argument named `{}`", name)) + diag.struct_span_err(span, &format!("duplicate argument named `{}`", name)) .span_label(args.operands[prev].1, "previously here") .span_label(span, "duplicate argument") .emit(); continue; } if !args.reg_args.is_empty() { - let mut err = ecx.struct_span_err( + let mut err = diag.struct_span_err( span, "named arguments cannot follow explicit register arguments", ); @@ -243,7 +244,7 @@ args.named_args.insert(name, slot); } else { if !args.named_args.is_empty() || !args.reg_args.is_empty() { - let mut err = ecx.struct_span_err( + let mut err = diag.struct_span_err( span, "positional arguments cannot follow named arguments \ or explicit register arguments", @@ -264,21 +265,21 @@ && args.options.contains(ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - ecx.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") + diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && args.options.contains(ast::InlineAsmOptions::NORETURN) { let spans = args.options_spans.clone(); - ecx.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") + diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - ecx.struct_span_err( + diag.struct_span_err( spans, "the `pure` option must be combined with either `nomem` or `readonly`", ) @@ -309,14 +310,14 @@ } } if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { - ecx.struct_span_err( + diag.struct_span_err( args.options_spans.clone(), "asm with the `pure` option must have at least one output", ) .emit(); } if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { - let err = ecx + let err = diag .struct_span_err(outputs_sp, "asm outputs are not allowed with the `noreturn` option"); // Bail out now since this is likely to confuse MIR @@ -325,7 +326,7 @@ if args.clobber_abis.len() > 0 { if is_global_asm { - let err = ecx.struct_span_err( + let err = diag.struct_span_err( args.clobber_abis.iter().map(|(_, span)| *span).collect::>(), "`clobber_abi` cannot be used with `global_asm!`", ); @@ -334,7 +335,7 @@ return Err(err); } if !regclass_outputs.is_empty() { - ecx.struct_span_err( + diag.struct_span_err( regclass_outputs.clone(), "asm with `clobber_abi` must specify explicit registers for outputs", ) @@ -420,6 +421,8 @@ try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX); } else if p.eat_keyword(kw::Raw) { try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW); + } else if p.eat_keyword(sym::may_unwind) { + try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND); } else { return p.unexpected(); } @@ -570,7 +573,7 @@ template_snippet.as_ref().map(|s| Symbol::intern(s)), template_sp, )); - let template_str = &template_str.as_str(); + let template_str = template_str.as_str(); if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch { let find_span = |needle: &str| -> Span { @@ -710,7 +713,7 @@ Some(&idx) => Some(idx), None => { let msg = format!("there is no argument named `{}`", name); - ecx.struct_span_err(span, &msg[..]).emit(); + ecx.struct_span_err(span, &msg).emit(); None } }, @@ -806,7 +809,7 @@ }) } -pub fn expand_asm<'cx>( +pub(super) fn expand_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -833,7 +836,7 @@ } } -pub fn expand_global_asm<'cx>( +pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/assert.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/assert.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/assert.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/assert.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::panic::use_panic_2021; +use crate::edition_panic::use_panic_2021; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; @@ -11,7 +11,7 @@ use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; use rustc_feature::Features; -use rustc_parse::parser::ForceCollect; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::utils::FlattenNonterminals; use rustc_session::Session; use rustc_span::symbol::sym; @@ -25,6 +25,7 @@ annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval); vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)] } @@ -77,6 +78,10 @@ Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param), Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef), Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant), + Annotatable::Crate(mut krate) => { + vis.visit_crate(&mut krate); + Some(Annotatable::Crate(krate)) + } } } @@ -101,6 +106,7 @@ Annotatable::Param(param) => finder.visit_param(¶m), Annotatable::FieldDef(field) => finder.visit_field_def(&field), Annotatable::Variant(variant) => finder.visit_variant(&variant), + Annotatable::Crate(krate) => finder.visit_crate(krate), }; finder.has_cfg_or_cfg_attr } @@ -138,8 +144,34 @@ // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // FIXME - get rid of this clone - let nt = annotatable.clone().into_nonterminal(); + let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable { + Annotatable::Item(_) => { + |parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) + } + Annotatable::TraitItem(_) => |parser| { + Annotatable::TraitItem( + parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::ImplItem(_) => |parser| { + Annotatable::ImplItem( + parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::ForeignItem(_) => |parser| { + Annotatable::ForeignItem( + parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::Stmt(_) => |parser| { + Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) + }, + Annotatable::Expr(_) => { + |parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap()) + } + _ => unreachable!(), + }; + let nt = annotatable.into_nonterminal(); let mut orig_tokens = rustc_parse::nt_to_tokenstream( &nt, @@ -173,25 +205,7 @@ let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); parser.capture_cfg = true; - annotatable = match annotatable { - Annotatable::Item(_) => { - Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) - } - Annotatable::TraitItem(_) => Annotatable::TraitItem( - parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::ImplItem(_) => Annotatable::ImplItem( - parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::ForeignItem(_) => Annotatable::ForeignItem( - parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::Stmt(_) => { - Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) - } - Annotatable::Expr(_) => Annotatable::Expr(parser.parse_expr_force_collect().unwrap()), - _ => unreachable!(), - }; + annotatable = parse_annotatable_with(&mut parser); // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring // our attribute target will correctly the tokens as well. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_bytes.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_bytes.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_bytes.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_bytes.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,192 @@ +use rustc_ast as ast; +use rustc_ast::{ptr::P, tokenstream::TokenStream}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::Applicability; +use rustc_expand::base::{self, DummyResult}; + +/// Emits errors for literal expressions that are invalid inside and outside of an array. +fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P, is_nested: bool) { + let lit = if let ast::ExprKind::Lit(lit) = &expr.kind { + lit + } else { + unreachable!(); + }; + match lit.kind { + ast::LitKind::Char(_) => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals"); + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try using a byte character", + format!("b{}", snippet), + Applicability::MachineApplicable, + ) + .emit(); + } + } + ast::LitKind::Str(_, _) => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals"); + // suggestion would be invalid if we are nested + if !is_nested { + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try using a byte string", + format!("b{}", snippet), + Applicability::MachineApplicable, + ); + } + } + err.emit(); + } + ast::LitKind::Float(_, _) => { + cx.span_err(expr.span, "cannot concatenate float literals"); + } + ast::LitKind::Bool(_) => { + cx.span_err(expr.span, "cannot concatenate boolean literals"); + } + ast::LitKind::Err(_) => {} + ast::LitKind::Int(_, _) if !is_nested => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals"); + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try wrapping the number in an array", + format!("[{}]", snippet), + Applicability::MachineApplicable, + ); + } + err.emit(); + } + ast::LitKind::Int( + val, + ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8), + ) => { + assert!(val > u8::MAX.into()); // must be an error + cx.span_err(expr.span, "numeric literal is out of bounds"); + } + ast::LitKind::Int(_, _) => { + cx.span_err(expr.span, "numeric literal is not a `u8`"); + } + _ => unreachable!(), + } +} + +fn handle_array_element( + cx: &mut base::ExtCtxt<'_>, + has_errors: &mut bool, + missing_literals: &mut Vec, + expr: &P, +) -> Option { + match expr.kind { + ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => { + if !*has_errors { + cx.span_err(expr.span, "cannot concatenate doubly nested array"); + } + *has_errors = true; + None + } + ast::ExprKind::Lit(ref lit) => match lit.kind { + ast::LitKind::Int( + val, + ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8), + ) if val <= u8::MAX.into() => Some(val as u8), + + ast::LitKind::Byte(val) => Some(val), + ast::LitKind::ByteStr(_) => { + 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 + } + _ => { + if !*has_errors { + invalid_type_err(cx, expr, true); + } + *has_errors = true; + None + } + }, + _ => { + missing_literals.push(expr.span); + None + } + } +} + +pub fn expand_concat_bytes( + cx: &mut base::ExtCtxt<'_>, + sp: rustc_span::Span, + tts: TokenStream, +) -> Box { + let es = match base::get_exprs_from_tts(cx, sp, tts) { + Some(e) => e, + None => return DummyResult::any(sp), + }; + let mut accumulator = Vec::new(); + let mut missing_literals = vec![]; + let mut has_errors = false; + for e in es { + match e.kind { + ast::ExprKind::Array(ref exprs) => { + for expr in exprs { + if let Some(elem) = + handle_array_element(cx, &mut has_errors, &mut missing_literals, expr) + { + accumulator.push(elem); + } + } + } + ast::ExprKind::Repeat(ref expr, ref count) => { + if let ast::ExprKind::Lit(ast::Lit { + kind: ast::LitKind::Int(count_val, _), .. + }) = count.value.kind + { + if let Some(elem) = + handle_array_element(cx, &mut has_errors, &mut missing_literals, expr) + { + for _ in 0..count_val { + accumulator.push(elem); + } + } + } else { + cx.span_err(count.value.span, "repeat count is not a positive number"); + } + } + ast::ExprKind::Lit(ref lit) => match lit.kind { + ast::LitKind::Byte(val) => { + accumulator.push(val); + } + ast::LitKind::ByteStr(ref bytes) => { + accumulator.extend_from_slice(&bytes); + } + _ => { + if !has_errors { + invalid_type_err(cx, &e, false); + } + has_errors = true; + } + }, + ast::ExprKind::Err => { + has_errors = true; + } + _ => { + missing_literals.push(e.span); + } + } + } + if !missing_literals.is_empty() { + let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal"); + err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`"); + err.emit(); + return base::MacEager::expr(DummyResult::raw_expr(sp, true)); + } else if has_errors { + return base::MacEager::expr(DummyResult::raw_expr(sp, true)); + } + let sp = cx.with_def_site_ctxt(sp); + base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(accumulator)))) +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_idents.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_idents.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_idents.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat_idents.rs 2022-02-23 04:07:21.000000000 +0000 @@ -29,7 +29,7 @@ } else { if let TokenTree::Token(token) = e { if let Some((ident, _)) = token.ident() { - res_str.push_str(&ident.name.as_str()); + res_str.push_str(ident.name.as_str()); continue; } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/concat.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,7 @@ match e.kind { ast::ExprKind::Lit(ref lit) => match lit.kind { ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) => { - accumulator.push_str(&s.as_str()); + accumulator.push_str(s.as_str()); } ast::LitKind::Char(c) => { accumulator.push(c); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/derive.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/derive.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/derive.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/derive.rs 2022-02-23 04:07:21.000000000 +0000 @@ -121,7 +121,7 @@ fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { let help_msg = match lit.token.kind { - token::Str if rustc_lexer::is_ident(&lit.token.symbol.as_str()) => { + token::Str if rustc_lexer::is_ident(lit.token.symbol.as_str()) => { format!("try using `#[derive({})]`", lit.token.symbol) } _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -567,8 +567,11 @@ }) }); - let Generics { mut params, mut where_clause, span } = + let Generics { mut params, mut where_clause, .. } = self.generics.to_generics(cx, self.span, type_ident, generics); + where_clause.span = generics.where_clause.span; + let ctxt = self.span.ctxt(); + let span = generics.span.with_ctxt(ctxt); // Create the generic parameters params.extend(generics.params.iter().map(|param| match ¶m.kind { @@ -589,12 +592,12 @@ param.bounds.iter().cloned() ).collect(); - cx.typaram(self.span, param.ident, vec![], bounds, None) + cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, vec![], bounds, None) } GenericParamKind::Const { ty, kw_span, .. } => { let const_nodefault_kind = GenericParamKind::Const { ty: ty.clone(), - kw_span: *kw_span, + kw_span: kw_span.with_ctxt(ctxt), // We can't have default values inside impl block default: None, @@ -607,28 +610,27 @@ // and similarly for where clauses where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { - match *clause { - ast::WherePredicate::BoundPredicate(ref wb) => { + match clause { + ast::WherePredicate::BoundPredicate(wb) => { + let span = wb.span.with_ctxt(ctxt); ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: self.span, - bound_generic_params: wb.bound_generic_params.clone(), - bounded_ty: wb.bounded_ty.clone(), - bounds: wb.bounds.to_vec(), + span, + ..wb.clone() }) } - ast::WherePredicate::RegionPredicate(ref rb) => { + ast::WherePredicate::RegionPredicate(wr) => { + let span = wr.span.with_ctxt(ctxt); ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - span: self.span, - lifetime: rb.lifetime, - bounds: rb.bounds.to_vec(), + span, + ..wr.clone() }) } - ast::WherePredicate::EqPredicate(ref we) => { + ast::WherePredicate::EqPredicate(we) => { + let span = we.span.with_ctxt(ctxt); ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { id: ast::DUMMY_NODE_ID, - span: self.span, - lhs_ty: we.lhs_ty.clone(), - rhs_ty: we.rhs_ty.clone(), + span, + ..we.clone() }) } } @@ -691,13 +693,13 @@ .iter() .map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) + GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident)) } GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(self.span, param.ident)) + GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(self.span, param.ident)) + GenericArg::Const(cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } }) .collect(); @@ -764,8 +766,8 @@ self, struct_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, ) } else { method_def.expand_struct_method_body( @@ -773,8 +775,8 @@ self, struct_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, use_temporaries, ) }; @@ -813,8 +815,8 @@ self, enum_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, ) } else { method_def.expand_enum_method_body( @@ -823,7 +825,7 @@ enum_def, type_ident, self_args, - &nonself_args[..], + &nonself_args, ) }; @@ -845,16 +847,17 @@ nonself_args: &[P], fields: &SubstructureFields<'_>, ) -> P { + let span = trait_.span; let substructure = Substructure { type_ident, - method_ident: Ident::new(self.name, trait_.span), + method_ident: Ident::new(self.name, span), self_args, nonself_args, fields, }; let mut f = self.combine_substructure.borrow_mut(); let f: &mut CombineSubstructureFunc<'_> = &mut *f; - f(cx, trait_.span, &substructure) + f(cx, span, &substructure) } fn get_ret_ty( @@ -882,9 +885,10 @@ let mut nonself_args = Vec::new(); let mut arg_tys = Vec::new(); let mut nonstatic = false; + let span = trait_.span; let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr); + let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr); self_args.push(self_expr); nonstatic = true; @@ -893,11 +897,11 @@ }); for (ty, name) in self.args.iter() { - let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = Ident::new(*name, trait_.span); + let ast_ty = ty.to_ty(cx, span, type_ident, generics); + let ident = Ident::new(*name, span); arg_tys.push((ident, ast_ty)); - let arg_expr = cx.expr_ident(trait_.span, ident); + let arg_expr = cx.expr_ident(span, ident); match *ty { // for static methods, just treat any Self @@ -906,7 +910,7 @@ self_args.push(arg_expr); } Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => { - self_args.push(cx.expr_deref(trait_.span, arg_expr)) + self_args.push(cx.expr_deref(span, arg_expr)) } _ => { nonself_args.push(arg_expr); @@ -927,33 +931,33 @@ arg_types: Vec<(Ident, P)>, body: P, ) -> P { + let span = trait_.span; // Create the generics that aren't for `Self`. - let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); + let fn_generics = self.generics.to_generics(cx, span, type_ident, generics); let args = { let self_args = explicit_self.map(|explicit_self| { - let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span); + let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(span); ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident) }); - let nonself_args = - arg_types.into_iter().map(|(name, ty)| cx.param(trait_.span, name, ty)); + let nonself_args = arg_types.into_iter().map(|(name, ty)| cx.param(span, name, ty)); self_args.into_iter().chain(nonself_args).collect() }; let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); - let method_ident = Ident::new(self.name, trait_.span); + let method_ident = Ident::new(self.name, span); let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(trait_.span) } else { ast::Unsafe::No }; + let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No }; - let trait_lo_sp = trait_.span.shrink_to_lo(); + let trait_lo_sp = span.shrink_to_lo(); let sig = ast::FnSig { header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, decl: fn_decl, - span: trait_.span, + span, }; let defaultness = ast::Defaultness::Final; @@ -961,7 +965,7 @@ P(ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), - span: trait_.span, + span, vis: ast::Visibility { span: trait_lo_sp, kind: ast::VisibilityKind::Inherited, @@ -1024,11 +1028,11 @@ nonself_args: &[P], use_temporaries: bool, ) -> P { - let mut raw_fields = Vec::new(); // Vec<[fields of self], - // [fields of next Self arg], [etc]> + let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]> + let span = trait_.span; let mut patterns = Vec::new(); for i in 0..self_args.len() { - let struct_path = cx.path(trait_.span, vec![type_ident]); + let struct_path = cx.path(span, vec![type_ident]); let (pat, ident_expr) = trait_.create_struct_pattern( cx, struct_path, @@ -1048,7 +1052,7 @@ let mut other_fields: Vec> = raw_fields.collect(); first_field .map(|(span, opt_id, field, attrs)| FieldInfo { - span, + span: span.with_ctxt(trait_.span.ctxt()), name: opt_id, self_: field, other: other_fields @@ -1062,7 +1066,7 @@ }) .collect() } else { - cx.span_bug(trait_.span, "no `self` parameter for method in generic `derive`") + cx.span_bug(span, "no `self` parameter for method in generic `derive`") }; // body of the inner most destructuring match @@ -1079,11 +1083,7 @@ // structs. This is actually right-to-left, but it shouldn't // matter. for (arg_expr, pat) in iter::zip(self_args, patterns) { - body = cx.expr_match( - trait_.span, - arg_expr.clone(), - vec![cx.arm(trait_.span, pat.clone(), body)], - ) + body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)]) } body @@ -1193,7 +1193,7 @@ mut self_args: Vec>, nonself_args: &[P], ) -> P { - let sp = trait_.span; + let span = trait_.span; let variants = &enum_def.variants; let self_arg_names = iter::once("__self".to_string()) @@ -1208,7 +1208,7 @@ let self_arg_idents = self_arg_names .iter() - .map(|name| Ident::from_str_and_span(name, sp)) + .map(|name| Ident::from_str_and_span(name, span)) .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to @@ -1217,8 +1217,8 @@ let vi_idents = self_arg_names .iter() .map(|name| { - let vi_suffix = format!("{}_vi", &name[..]); - Ident::from_str_and_span(&vi_suffix, trait_.span) + let vi_suffix = format!("{}_vi", name); + Ident::from_str_and_span(&vi_suffix, span) }) .collect::>(); @@ -1226,7 +1226,7 @@ // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. let catch_all_substructure = - EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]); + EnumNonMatchingCollapsed(self_arg_idents, &variants, &vi_idents); let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); @@ -1248,7 +1248,7 @@ self_arg_name, ast::Mutability::Not, ); - (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Not)), idents) + (cx.pat(span, PatKind::Ref(p, ast::Mutability::Not)), idents) }; // A single arm has form (&VariantK, &VariantK, ...) => BodyK @@ -1261,13 +1261,13 @@ idents }; for self_arg_name in &self_arg_names[1..] { - let (p, idents) = mk_self_pat(cx, &self_arg_name[..]); + let (p, idents) = mk_self_pat(cx, &self_arg_name); subpats.push(p); self_pats_idents.push(idents); } // Here is the pat = `(&VariantK, &VariantK, ...)` - let single_pat = cx.pat_tuple(sp, subpats); + let single_pat = cx.pat_tuple(span, subpats); // For the BodyK, we need to delegate to our caller, // passing it an EnumMatching to indicate which case @@ -1284,7 +1284,7 @@ .into_iter() .enumerate() // For each arg field of self, pull out its getter expr ... - .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| { + .map(|(field_index, (span, opt_ident, self_getter_expr, attrs))| { // ... but FieldInfo also wants getter expr // for matching other arguments of Self type; // so walk across the *other* self_pats_idents @@ -1307,7 +1307,7 @@ .collect::>>(); FieldInfo { - span: sp, + span, name: opt_ident, self_: self_getter_expr, other: others, @@ -1330,7 +1330,7 @@ &substructure, ); - cx.arm(sp, single_pat, arm_expr) + cx.arm(span, single_pat, arm_expr) }) .collect(); @@ -1353,12 +1353,12 @@ // Since we know that all the arguments will match if we reach // the match expression we add the unreachable intrinsics as the // result of the catch all which should help llvm in optimizing it - Some(deriving::call_unreachable(cx, sp)) + Some(deriving::call_unreachable(cx, span)) } _ => None, }; if let Some(arm) = default { - match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm)); + match_arms.push(cx.arm(span, cx.pat_wild(span), arm)); } // We will usually need the catch-all after matching the @@ -1392,23 +1392,23 @@ // We also build an expression which checks whether all discriminants are equal // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... - let mut discriminant_test = cx.expr_bool(sp, true); + let mut discriminant_test = cx.expr_bool(span, true); let mut first_ident = None; for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { - let self_addr = cx.expr_addr_of(sp, self_arg.clone()); + let self_addr = cx.expr_addr_of(span, self_arg.clone()); let variant_value = - deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); - let let_stmt = cx.stmt_let(sp, false, ident, variant_value); + deriving::call_intrinsic(cx, span, sym::discriminant_value, vec![self_addr]); + let let_stmt = cx.stmt_let(span, false, ident, variant_value); index_let_stmts.push(let_stmt); match first_ident { Some(first) => { - let first_expr = cx.expr_ident(sp, first); - let id = cx.expr_ident(sp, ident); - let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id); + let first_expr = cx.expr_ident(span, first); + let id = cx.expr_ident(span, ident); + let test = cx.expr_binary(span, BinOpKind::Eq, first_expr, id); discriminant_test = - cx.expr_binary(sp, BinOpKind::And, discriminant_test, test) + cx.expr_binary(span, BinOpKind::And, discriminant_test, test) } None => { first_ident = Some(ident); @@ -1430,8 +1430,8 @@ // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); + self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg)); + let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args)); // Lastly we create an expression which branches on all discriminants being equal // if discriminant_test { @@ -1445,10 +1445,10 @@ // else { // // } - let all_match = cx.expr_match(sp, match_arg, match_arms); - let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); + let all_match = cx.expr_match(span, match_arg, match_arms); + let arm_expr = cx.expr_if(span, discriminant_test, all_match, Some(arm_expr)); index_let_stmts.push(cx.stmt_expr(arm_expr)); - cx.expr_block(cx.block(sp, index_let_stmts)) + cx.expr_block(cx.block(span, index_let_stmts)) } else if variants.is_empty() { // As an additional wrinkle, For a zero-variant enum A, // currently the compiler @@ -1499,16 +1499,16 @@ // derive Debug on such a type could here generate code // that needs the feature gate enabled.) - deriving::call_unreachable(cx, sp) + deriving::call_unreachable(cx, span) } else { // Final wrinkle: the self_args are expressions that deref // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); - cx.expr_match(sp, match_arg, match_arms) + self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg)); + let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args)); + cx.expr_match(span, match_arg, match_arms) } } @@ -1556,11 +1556,9 @@ let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..)); match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx.span_bug( - self.span, - "a struct with named and unnamed \ - fields in generic `derive`", - ), + (false, false) => { + cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`") + } // named fields (_, false) => Named(named_idents), // unnamed fields diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -211,14 +211,6 @@ cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None) } -fn mk_generics(params: Vec, span: Span) -> Generics { - Generics { - params, - where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, - span, - } -} - /// Bounds on type parameters. #[derive(Clone)] pub struct Bounds { @@ -236,7 +228,7 @@ self_ty: Ident, self_generics: &Generics, ) -> Generics { - let generic_params = self + let params = self .bounds .iter() .map(|t| { @@ -245,7 +237,11 @@ }) .collect(); - mk_generics(generic_params, span) + Generics { + params, + where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, + span, + } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/edition_panic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/edition_panic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/edition_panic.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/edition_panic.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,86 @@ +use rustc_ast::ptr::P; +use rustc_ast::tokenstream::{DelimSpan, TokenStream}; +use rustc_ast::*; +use rustc_expand::base::*; +use rustc_span::edition::Edition; +use rustc_span::symbol::sym; +use rustc_span::Span; + +// This expands to either +// - `$crate::panic::panic_2015!(...)` or +// - `$crate::panic::panic_2021!(...)` +// depending on the edition. +// +// This is used for both std::panic!() and core::panic!(). +// +// `$crate` will refer to either the `std` or `core` crate depending on which +// one we're expanding from. +pub fn expand_panic<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { + let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; + expand(mac, cx, sp, tts) +} + +// This expands to either +// - `$crate::panic::unreachable_2015!(...)` or +// - `$crate::panic::unreachable_2021!(...)` +// depending on the edition. +pub fn expand_unreachable<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { + let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 }; + expand(mac, cx, sp, tts) +} + +fn expand<'cx>( + mac: rustc_span::Symbol, + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { + let sp = cx.with_call_site_ctxt(sp); + + MacEager::expr( + cx.expr( + sp, + ExprKind::MacCall(MacCall { + path: Path { + span: sp, + segments: cx + .std_path(&[sym::panic, mac]) + .into_iter() + .map(|ident| PathSegment::from_ident(ident)) + .collect(), + tokens: None, + }, + args: P(MacArgs::Delimited( + DelimSpan::from_single(sp), + MacDelimiter::Parenthesis, + tts, + )), + prior_type_ascription: None, + }), + ), + ) +} + +pub fn use_panic_2021(mut span: Span) -> bool { + // To determine the editon, we check the first span up the expansion + // stack that does not have #[allow_internal_unstable(edition_panic)]. + // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) + loop { + let expn = span.ctxt().outer_expn_data(); + if let Some(features) = expn.allow_internal_unstable { + if features.iter().any(|&f| f == sym::edition_panic) { + span = expn.call_site; + continue; + } + } + break expn.edition >= Edition::Edition2021; + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/env.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/env.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/env.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/env.rs 2022-02-23 04:07:21.000000000 +0000 @@ -80,11 +80,11 @@ } let sp = cx.with_def_site_ctxt(sp); - let value = env::var(&*var.as_str()).ok().as_deref().map(Symbol::intern); + let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { - cx.span_err(sp, &msg.as_str()); + cx.span_err(sp, msg.as_str()); return DummyResult::any(sp); } Some(value) => cx.expr_str(sp, value), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,9 +13,9 @@ fn test_escape() { assert_eq!(pns("has no escapes"), None); assert_eq!(pns("has no escapes, either %"), None); - assert_eq!(pns("*so* has a %% escape"), Some((S::Escape, " escape"))); - assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); - assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); + assert_eq!(pns("*so* has a %% escape"), Some((S::Escape((11, 13)), " escape"))); + assert_eq!(pns("%% leading escape"), Some((S::Escape((0, 2)), " leading escape"))); + assert_eq!(pns("trailing escape %%"), Some((S::Escape((16, 18)), ""))); } #[test] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format_foreign.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,28 +7,29 @@ pub enum Substitution<'a> { /// A formatted output substitution with its internal byte offset. Format(Format<'a>), - /// A literal `%%` escape. - Escape, + /// A literal `%%` escape, with its start and end indices. + Escape((usize, usize)), } impl<'a> Substitution<'a> { pub fn as_str(&self) -> &str { match *self { Substitution::Format(ref fmt) => fmt.span, - Substitution::Escape => "%%", + Substitution::Escape(_) => "%%", } } pub fn position(&self) -> Option { match *self { Substitution::Format(ref fmt) => Some(fmt.position), - _ => None, + Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), } } pub fn set_position(&mut self, start: usize, end: usize) { - if let Substitution::Format(ref mut fmt) = self { - fmt.position = InnerSpan::new(start, end); + match self { + Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end), + Substitution::Escape(ref mut pos) => *pos = (start, end), } } @@ -39,7 +40,7 @@ pub fn translate(&self) -> Result> { match *self { Substitution::Format(ref fmt) => fmt.translate(), - Substitution::Escape => Err(None), + Substitution::Escape(_) => Err(None), } } } @@ -304,14 +305,9 @@ fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - match sub { - Substitution::Format(_) => { - if let Some(inner_span) = sub.position() { - sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos); - self.pos += inner_span.end; - } - } - Substitution::Escape => self.pos += 2, + if let Some(InnerSpan { start, end }) = sub.position() { + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; } Some(sub) } @@ -340,7 +336,7 @@ let at = { let start = s.find('%')?; if let '%' = s[start + 1..].chars().next()? { - return Some((Substitution::Escape, &s[start + 2..])); + return Some((Substitution::Escape((start, start + 2)), &s[start + 2..])); } Cur::new_at(s, start) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/format.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,6 +23,7 @@ enum Position { Exact(usize), + Capture(usize), Named(Symbol), } @@ -47,6 +48,8 @@ /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]` /// * `names` (in JSON): `{"foo": 2}` args: Vec>, + /// The number of arguments that were added by implicit capturing. + num_captured_args: usize, /// Placeholder slot numbers indexed by argument. arg_types: Vec>, /// Unique format specs seen for each argument. @@ -88,8 +91,8 @@ /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"` /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"` /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}` - /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]` - count_args: Vec, + /// * `count_args`: `vec![0, 5, 3]` + count_args: Vec, /// Relative slot numbers for count arguments. count_positions: FxHashMap, /// Number of count slots assigned. @@ -229,6 +232,11 @@ } impl<'a, 'b> Context<'a, 'b> { + /// The number of arguments that were explicitly given. + fn num_args(&self) -> usize { + self.args.len() - self.num_captured_args + } + fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) { // NOTE: the `unwrap_or` branch is needed in case of invalid format // arguments, e.g., `format_args!("{foo}")`. @@ -343,7 +351,7 @@ } fn describe_num_args(&self) -> Cow<'_, str> { - match self.args.len() { + match self.num_args() { 0 => "no arguments were given".into(), 1 => "there is 1 argument".into(), x => format!("there are {} arguments", x).into(), @@ -369,7 +377,7 @@ let count = self.pieces.len() + self.arg_with_formatting.iter().filter(|fmt| fmt.precision_span.is_some()).count(); - if self.names.is_empty() && !numbered_position_args && count != self.args.len() { + if self.names.is_empty() && !numbered_position_args && count != self.num_args() { e = self.ecx.struct_span_err( sp, &format!( @@ -417,7 +425,7 @@ if let Some(span) = fmt.precision_span { let span = self.fmtsp.from_inner(span); match fmt.precision { - parse::CountIsParam(pos) if pos > self.args.len() => { + parse::CountIsParam(pos) if pos > self.num_args() => { e.span_label( span, &format!( @@ -460,7 +468,7 @@ if let Some(span) = fmt.width_span { let span = self.fmtsp.from_inner(span); match fmt.width { - parse::CountIsParam(pos) if pos > self.args.len() => { + parse::CountIsParam(pos) if pos > self.num_args() => { e.span_label( span, &format!( @@ -492,12 +500,15 @@ /// Actually verifies and tracks a given format placeholder /// (a.k.a. argument). fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { + if let Exact(arg) = arg { + if arg >= self.num_args() { + self.invalid_refs.push((arg, self.curpiece)); + return; + } + } + match arg { - Exact(arg) => { - if self.args.len() <= arg { - self.invalid_refs.push((arg, self.curpiece)); - return; - } + Exact(arg) | Capture(arg) => { match ty { Placeholder(_) => { // record every (position, type) combination only once @@ -513,7 +524,7 @@ if let Entry::Vacant(e) = self.count_positions.entry(arg) { let i = self.count_positions_count; e.insert(i); - self.count_args.push(Exact(arg)); + self.count_args.push(arg); self.count_positions_count += 1; } } @@ -524,7 +535,7 @@ match self.names.get(&name) { Some(&idx) => { // Treat as positional arg. - self.verify_arg_type(Exact(idx), ty) + self.verify_arg_type(Capture(idx), ty) } None => { // For the moment capturing variables from format strings expanded from macros is @@ -539,9 +550,10 @@ } else { self.fmtsp }; + self.num_captured_args += 1; self.args.push(self.ecx.expr_ident(span, Ident::new(name, span))); self.names.insert(name, idx); - self.verify_arg_type(Exact(idx), ty) + self.verify_arg_type(Capture(idx), ty) } else { let msg = format!("there is no argument named `{}`", name); let sp = if self.is_literal { @@ -549,7 +561,7 @@ } else { self.fmtsp }; - let mut err = self.ecx.struct_span_err(sp, &msg[..]); + let mut err = self.ecx.struct_span_err(sp, &msg); err.note(&format!( "did you intend to capture a variable `{}` from \ @@ -769,13 +781,12 @@ for arg_ty in self.arg_unique_types[i].iter() { args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i)); } - heads.push(self.ecx.expr_addr_of(e.span, e)); + // use the arg span for `&arg` so that borrowck errors + // point to the specific expression passed to the macro + // (the span is otherwise unavailable in MIR) + heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e)); } - for pos in self.count_args { - let index = match pos { - Exact(i) => i, - _ => panic!("should never happen"), - }; + for index in self.count_args { let span = spans_pos[index]; args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index)); } @@ -956,7 +967,7 @@ ast::StrStyle::Raw(raw) => Some(raw as usize), }; - let fmt_str = &fmt_str.as_str(); // for the suggestions below + let fmt_str = fmt_str.as_str(); // for the suggestions below let fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok(); let mut parser = parse::Parser::new( fmt_str, @@ -996,8 +1007,9 @@ e.note(¬e); } if let Some((label, span)) = err.secondary_label { - let sp = fmt_span.from_inner(span); - e.span_label(sp, label); + if efmt_kind_is_lit { + e.span_label(fmt_span.from_inner(span), label); + } } e.emit(); return DummyResult::raw_expr(sp, true); @@ -1010,6 +1022,7 @@ let mut cx = Context { ecx, args, + num_captured_args: 0, arg_types, arg_unique_types, names, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,6 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] -#![feature(iter_zip)] #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] @@ -20,28 +19,29 @@ use rustc_expand::proc_macro::BangProcMacro; use rustc_span::symbol::sym; -mod asm; mod assert; mod cfg; mod cfg_accessible; mod cfg_eval; mod compile_error; mod concat; +mod concat_bytes; mod concat_idents; mod derive; mod deriving; +mod edition_panic; mod env; mod format; mod format_foreign; mod global_allocator; mod llvm_asm; mod log_syntax; -mod panic; mod source_util; mod test; mod trace_macros; mod util; +pub mod asm; pub mod cmdline_attrs; pub mod proc_macro_harness; pub mod standard_library_imports; @@ -65,6 +65,7 @@ cfg: cfg::expand_cfg, column: source_util::expand_column, compile_error: compile_error::expand_compile_error, + concat_bytes: concat_bytes::expand_concat_bytes, concat_idents: concat_idents::expand_concat_idents, concat: concat::expand_concat, env: env::expand_env, @@ -81,8 +82,9 @@ log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, option_env: env::expand_option_env, - core_panic: panic::expand_panic, - std_panic: panic::expand_panic, + core_panic: edition_panic::expand_panic, + std_panic: edition_panic::expand_panic, + unreachable: edition_panic::expand_unreachable, stringify: source_util::expand_stringify, trace_macros: trace_macros::expand_trace_macros, } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/panic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/panic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/panic.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/panic.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -use rustc_ast::ptr::P; -use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::*; -use rustc_expand::base::*; -use rustc_span::edition::Edition; -use rustc_span::symbol::sym; -use rustc_span::Span; - -// This expands to either -// - `$crate::panic::panic_2015!(...)` or -// - `$crate::panic::panic_2021!(...)` -// depending on the edition. -// -// This is used for both std::panic!() and core::panic!(). -// -// `$crate` will refer to either the `std` or `core` crate depending on which -// one we're expanding from. -pub fn expand_panic<'cx>( - cx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: TokenStream, -) -> Box { - let panic = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; - - let sp = cx.with_call_site_ctxt(sp); - - MacEager::expr( - cx.expr( - sp, - ExprKind::MacCall(MacCall { - path: Path { - span: sp, - segments: cx - .std_path(&[sym::panic, panic]) - .into_iter() - .map(|ident| PathSegment::from_ident(ident)) - .collect(), - tokens: None, - }, - args: P(MacArgs::Delimited( - DelimSpan::from_single(sp), - MacDelimiter::Parenthesis, - tts, - )), - prior_type_ascription: None, - }), - ), - ) -} - -pub fn use_panic_2021(mut span: Span) -> bool { - // To determine the editon, we check the first span up the expansion - // stack that does not have #[allow_internal_unstable(edition_panic)]. - // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) - loop { - let expn = span.ctxt().outer_expn_data(); - if let Some(features) = expn.allow_internal_unstable { - if features.iter().any(|&f| f == sym::edition_panic) { - span = expn.call_site; - continue; - } - } - break expn.edition >= Edition::Edition2021; - } -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test_harness.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test_harness.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test_harness.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test_harness.rs 2022-02-23 04:07:21.000000000 +0000 @@ -84,9 +84,35 @@ tests: Vec, } +impl TestHarnessGenerator<'_> { + fn add_test_cases(&mut self, node_id: ast::NodeId, span: Span, prev_tests: Vec) { + let mut tests = mem::replace(&mut self.tests, prev_tests); + + if !tests.is_empty() { + // Create an identifier that will hygienically resolve the test + // case name, even in another module. + let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( + span, + AstPass::TestHarness, + &[], + Some(node_id), + ); + for test in &mut tests { + // See the comment on `mk_main` for why we're using + // `apply_mark` directly. + test.ident.span = + test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque); + } + self.cx.test_cases.extend(tests); + } + } +} + impl<'a> MutVisitor for TestHarnessGenerator<'a> { fn visit_crate(&mut self, c: &mut ast::Crate) { + let prev_tests = mem::take(&mut self.tests); noop_visit_crate(c, self); + self.add_test_cases(ast::CRATE_NODE_ID, c.span, prev_tests); // Create a main function to run our tests c.items.push(mk_main(&mut self.cx)); @@ -103,34 +129,10 @@ // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(..) = item.kind { - let tests = mem::take(&mut self.tests); + if let ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) = item.kind { + let prev_tests = mem::take(&mut self.tests); noop_visit_item_kind(&mut item.kind, self); - let mut tests = mem::replace(&mut self.tests, tests); - - if !tests.is_empty() { - let parent = - if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id }; - // Create an identifier that will hygienically resolve the test - // case name, even in another module. - let inner_span = match item.kind { - ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span, - _ => unreachable!(), - }; - let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( - inner_span, - AstPass::TestHarness, - &[], - Some(parent), - ); - for test in &mut tests { - // See the comment on `mk_main` for why we're using - // `apply_mark` directly. - test.ident.span = - test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque); - } - self.cx.test_cases.extend(tests); - } + self.add_test_cases(item.id, span, prev_tests); } smallvec![P(item)] } @@ -146,7 +148,7 @@ } else if sess.contains_name(&item.attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { - if depth == 1 { + if depth == 0 { // This is a top-level function so can be 'main' EntryPointType::MainNamed } else { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/test.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,6 @@ /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::attr; @@ -27,6 +27,7 @@ anno_item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::test_case); + warn_on_duplicate_attribute(&ecx, &anno_item, sym::test_case); if !ecx.ecfg.should_test { return vec![]; @@ -55,6 +56,7 @@ item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::test); + warn_on_duplicate_attribute(&cx, &item, sym::test); expand_test_or_bench(cx, attr_sp, item, false) } @@ -65,6 +67,7 @@ item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::bench); + warn_on_duplicate_attribute(&cx, &item, sym::bench); expand_test_or_bench(cx, attr_sp, item, true) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_builtin_macros/src/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,7 @@ -use rustc_ast::MetaItem; -use rustc_expand::base::ExtCtxt; +use rustc_ast::{Attribute, MetaItem}; +use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_feature::AttributeTemplate; +use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; use rustc_parse::validate_attr; use rustc_span::Symbol; @@ -10,3 +11,33 @@ let attr = ecx.attribute(meta_item.clone()); validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template); } + +/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when +/// an attribute may have been mistakenly duplicated. +pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { + let attrs: Option<&[Attribute]> = match item { + Annotatable::Item(item) => Some(&item.attrs), + Annotatable::TraitItem(item) => Some(&item.attrs), + Annotatable::ImplItem(item) => Some(&item.attrs), + Annotatable::ForeignItem(item) => Some(&item.attrs), + Annotatable::Expr(expr) => Some(&expr.attrs), + Annotatable::Arm(arm) => Some(&arm.attrs), + Annotatable::ExprField(field) => Some(&field.attrs), + Annotatable::PatField(field) => Some(&field.attrs), + Annotatable::GenericParam(param) => Some(¶m.attrs), + Annotatable::Param(param) => Some(¶m.attrs), + Annotatable::FieldDef(def) => Some(&def.attrs), + Annotatable::Variant(variant) => Some(&variant.attrs), + _ => None, + }; + if let Some(attrs) = attrs { + if let Some(attr) = ecx.sess.find_by_name(attrs, name) { + ecx.parse_sess().buffer_lint( + DUPLICATE_MACRO_ATTRIBUTES, + attr.span, + ecx.current_expansion.lint_node_id, + "duplicated attribute", + ); + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock 2022-02-23 04:07:21.000000000 +0000 @@ -40,9 +40,9 @@ [[package]] name = "cc" -version = "1.0.70" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -56,7 +56,7 @@ [[package]] name = "compiler_builtins" -version = "0.1.50" +version = "0.1.66" dependencies = [ "rustc-std-workspace-core", ] @@ -67,9 +67,9 @@ [[package]] name = "dlmalloc" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254" +checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e" dependencies = [ "compiler_builtins", "libc", @@ -132,9 +132,9 @@ [[package]] name = "libc" -version = "0.2.102" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" dependencies = [ "rustc-std-workspace-core", ] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_backend.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_backend.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_backend.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_backend.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,9 +2,29 @@ use std::path::{Path, PathBuf}; use std::process::Command; -pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { +pub(crate) fn build_backend( + channel: &str, + host_triple: &str, + use_unstable_features: bool, +) -> PathBuf { let mut cmd = Command::new("cargo"); - cmd.arg("build").arg("--target").arg(host_triple).arg("--features").arg("unstable-features"); + cmd.arg("build").arg("--target").arg(host_triple); + + cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode + + let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default(); + + if env::var("CI").as_ref().map(|val| &**val) == Ok("true") { + // Deny warnings on CI + rustflags += " -Dwarnings"; + + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + cmd.env("CARGO_BUILD_INCREMENTAL", "false"); + } + + if use_unstable_features { + cmd.arg("--features").arg("unstable-features"); + } match channel { "debug" => {} @@ -14,25 +34,20 @@ _ => unreachable!(), } + // Set the rpath to make the cg_clif executable find librustc_codegen_cranelift without changing + // LD_LIBRARY_PATH if cfg!(unix) { if cfg!(target_os = "macos") { - cmd.env( - "RUSTFLAGS", - "-Csplit-debuginfo=unpacked \ + rustflags += " -Csplit-debuginfo=unpacked \ -Clink-arg=-Wl,-rpath,@loader_path/../lib \ - -Zosx-rpath-install-name" - .to_string() - + env::var("RUSTFLAGS").as_deref().unwrap_or(""), - ); + -Zosx-rpath-install-name"; } else { - cmd.env( - "RUSTFLAGS", - "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string() - + env::var("RUSTFLAGS").as_deref().unwrap_or(""), - ); + rustflags += " -Clink-arg=-Wl,-rpath=$ORIGIN/../lib "; } } + cmd.env("RUSTFLAGS", rustflags); + eprintln!("[BUILD] rustc_codegen_cranelift"); crate::utils::spawn_and_wait(cmd); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,9 +46,9 @@ // Build and copy cargo wrapper let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd - .arg("scripts/cargo.rs") + .arg("scripts/cargo-clif.rs") .arg("-o") - .arg(target_dir.join("cargo")) + .arg(target_dir.join("cargo-clif")) .arg("-g"); spawn_and_wait(build_cargo_wrapper_cmd); @@ -193,8 +193,7 @@ "RUSTC", env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"), ); - // FIXME Enable incremental again once rust-lang/rust#74946 is fixed - build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); + build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); spawn_and_wait(build_cmd); // Copy all relevant files to the sysroot diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/prepare.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/prepare.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/prepare.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/build_system/prepare.rs 2022-02-23 04:07:21.000000000 +0000 @@ -30,7 +30,7 @@ clone_repo( "portable-simd", "https://github.com/rust-lang/portable-simd", - "8cf7a62e5d2552961df51e5200aaa5b7c890a4bf", + "b8d6b6844602f80af79cd96401339ec594d472d8", ); apply_patches("portable-simd", Path::new("portable-simd")); @@ -92,7 +92,7 @@ clone_repo( "build_sysroot/compiler-builtins", "https://github.com/rust-lang/compiler-builtins.git", - "0.1.50", + "0.1.66", ); apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.lock rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.lock --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.lock 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.lock 2022-02-23 04:07:21.000000000 +0000 @@ -4,9 +4,9 @@ [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "ar" @@ -21,9 +21,9 @@ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-if" @@ -33,16 +33,18 @@ [[package]] name = "cranelift-bforest" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -57,8 +59,9 @@ [[package]] name = "cranelift-codegen-meta" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -66,18 +69,21 @@ [[package]] name = "cranelift-codegen-shared" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be" [[package]] name = "cranelift-entity" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a" [[package]] name = "cranelift-frontend" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525" dependencies = [ "cranelift-codegen", "log", @@ -87,8 +93,9 @@ [[package]] name = "cranelift-jit" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e8f0d60fb5d67f7a1e5c49db38ba96d1c846921faef02085fc5590b74781747" dependencies = [ "anyhow", "cranelift-codegen", @@ -104,8 +111,9 @@ [[package]] name = "cranelift-module" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ac7e0959cbe7ddc9cc21209f0319e611a57f9fcb2b723861fe7ef2017e651" dependencies = [ "anyhow", "cranelift-codegen", @@ -115,8 +123,9 @@ [[package]] name = "cranelift-native" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b" dependencies = [ "cranelift-codegen", "libc", @@ -125,8 +134,9 @@ [[package]] name = "cranelift-object" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55500d0fc9bb05c0944fc4506649249d28f55bd4fe95b87f0e55bf41058f0e6d" dependencies = [ "anyhow", "cranelift-codegen", @@ -138,9 +148,9 @@ [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ "cfg-if", ] @@ -172,9 +182,9 @@ [[package]] name = "libc" -version = "0.2.98" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libloading" @@ -206,15 +216,15 @@ [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "object" -version = "0.26.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "crc32fast", "indexmap", @@ -223,9 +233,9 @@ [[package]] name = "regalloc" -version = "0.0.31" +version = "0.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4" dependencies = [ "log", "rustc-hash", @@ -271,15 +281,15 @@ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "target-lexicon" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0652da4c4121005e9ed22b79f6c5f2d9e2752906b53a33e9490489ba421a6fb" +checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" [[package]] name = "winapi" diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -8,23 +8,23 @@ [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", features = ["unwind", "all-arch"] } -cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", optional = true } -cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git" } +cranelift-codegen = { version = "0.78.0", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.78.0" +cranelift-module = "0.78.0" +cranelift-native = "0.78.0" +cranelift-jit = { version = "0.78.0", optional = true } +cranelift-object = "0.78.0" target-lexicon = "0.12.0" gimli = { version = "0.25.0", default-features = false, features = ["write"]} -object = { version = "0.26.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.0.2" libloading = { version = "0.6.0", optional = true } smallvec = "1.6.1" +[patch.crates-io] # Uncomment to use local checkout of cranelift -#[patch."https://github.com/bytecodealliance/wasmtime.git"] #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } #cranelift-frontend = { path = "../wasmtime/cranelift/frontend" } #cranelift-module = { path = "../wasmtime/cranelift/module" } @@ -32,7 +32,6 @@ #cranelift-jit = { path = "../wasmtime/cranelift/jit" } #cranelift-object = { path = "../wasmtime/cranelift/object" } -#[patch.crates-io] #gimli = { path = "../" } [features] @@ -41,31 +40,12 @@ jit = ["cranelift-jit", "libloading"] inline_asm = [] -[profile.dev] -# By compiling dependencies with optimizations, performing tests gets much faster. -opt-level = 3 - -[profile.dev.package.rustc_codegen_cranelift] -# Disabling optimizations for cg_clif itself makes compilation after a change faster. -opt-level = 0 - -[profile.release.package.rustc_codegen_cranelift] -incremental = true - # Disable optimizations and debuginfo of build scripts and some of the heavy build deps, as the # execution time of build scripts is so fast that optimizing them slows down the total build time. -[profile.dev.build-override] -opt-level = 0 -debug = false - [profile.release.build-override] opt-level = 0 debug = false -[profile.dev.package.cranelift-codegen-meta] -opt-level = 0 -debug = false - [profile.release.package.cranelift-codegen-meta] opt-level = 0 debug = false diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/docs/usage.md rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/docs/usage.md --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/docs/usage.md 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/docs/usage.md 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo build +$ $cg_clif_dir/build/cargo-clif build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. @@ -32,7 +32,7 @@ > The jit mode will probably need cargo integration to make this possible. ```bash -$ $cg_clif_dir/build/cargo jit +$ $cg_clif_dir/build/cargo-clif jit ``` or @@ -45,7 +45,7 @@ first called. ```bash -$ $cg_clif_dir/build/cargo lazy-jit +$ $cg_clif_dir/build/cargo-clif lazy-jit ``` ## Shell diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,60 @@ +// Copied from rustc ui test suite + +// run-pass +// +// Test that we can handle unsized types with an extern type tail part. +// Regression test for issue #91827. + +#![feature(const_ptr_offset_from)] +#![feature(const_slice_from_raw_parts)] +#![feature(extern_types)] + +use std::ptr::addr_of; + +extern "C" { + type Opaque; +} + +unsafe impl Sync for Opaque {} + +#[repr(C)] +pub struct List { + len: usize, + data: [T; 0], + tail: Opaque, +} + +#[repr(C)] +pub struct ListImpl { + len: usize, + data: [T; N], +} + +impl List { + const fn as_slice(&self) -> &[T] { + unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) } + } +} + +impl ListImpl { + const fn as_list(&self) -> &List { + unsafe { std::mem::transmute(self) } + } +} + +pub static A: ListImpl = ListImpl { + len: 3, + data: [5, 6, 7], +}; +pub static A_REF: &'static List = A.as_list(); +pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); + +const fn tail_offset(list: &List) -> isize { + unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List as *const u8) } +} + +fn main() { + assert_eq!(A_REF.as_slice(), &[5, 6, 7]); + // Check that interpreter and code generation agree about the position of the tail field. + assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF)); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs 2022-02-23 04:07:21.000000000 +0000 @@ -129,6 +129,7 @@ return_u128_pair(); } +#[allow(unreachable_code)] // FIXME false positive fn main() { take_unique(Unique { pointer: 0 as *const (), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml 2022-02-23 04:07:21.000000000 +0000 @@ -5,6 +5,21 @@ - pull_request jobs: + rustfmt: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + + - name: Install rustfmt + run: | + rustup component add rustfmt + + - name: Rustfmt + run: | + cargo fmt --check + build: runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -65,6 +80,12 @@ git config --global user.name "User" ./y.rs prepare + - name: Build without unstable features + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} + # This is the config rust-lang/rust uses for builds + run: ./y.rs build --no-unstable-features + - name: Build run: ./y.rs build --sysroot none @@ -152,11 +173,12 @@ ./y.exe build - #- name: Package prebuilt cg_clif - # run: tar cvfJ cg_clif.tar.xz build + - name: Package prebuilt cg_clif + # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs + run: tar cvf cg_clif.tar build - #- name: Upload prebuilt cg_clif - # uses: actions/upload-artifact@v2 - # with: - # name: cg_clif-${{ runner.os }} - # path: cg_clif.tar.xz + - name: Upload prebuilt cg_clif + uses: actions/upload-artifact@v2 + with: + name: cg_clif-${{ runner.os }} + path: cg_clif.tar diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,59 @@ +name: Test nightly Cranelift + +on: + push: + schedule: + - cron: '17 1 * * *' # At 01:17 UTC every day. + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + + - name: Cache cargo installed crates + uses: actions/cache@v2 + with: + path: ~/.cargo/bin + key: ubuntu-latest-cargo-installed-crates + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./y.rs prepare + + - name: Patch Cranelift + run: | + sed -i 's/cranelift-codegen = { version = "\w*.\w*.\w*", features = \["unwind", "all-arch"\] }/cranelift-codegen = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", features = ["unwind", "all-arch"] }/' Cargo.toml + sed -i 's/cranelift-frontend = "\w*.\w*.\w*"/cranelift-frontend = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-module = "\w*.\w*.\w*"/cranelift-module = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-native = "\w*.\w*.\w*"/cranelift-native = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-jit = { version = "\w*.\w*.\w*", optional = true }/cranelift-jit = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", optional = true }/' Cargo.toml + sed -i 's/cranelift-object = "\w*.\w*.\w*"/cranelift-object = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + + sed -i 's/gimli = { version = "0.25.0", default-features = false, features = \["write"\]}/gimli = { version = "0.26.1", default-features = false, features = ["write"] }/' Cargo.toml + + cat Cargo.toml + + - name: Build without unstable features + # This is the config rust-lang/rust uses for builds + run: ./y.rs build --no-unstable-features + + - name: Build + run: ./y.rs build --sysroot none + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + # Reduce amount of benchmark runs as they are slow + export COMPILE_RUNS=2 + export RUN_RUNS=2 + + # Enable extra checks + export CG_CLIF_ENABLE_VERIFIER=1 + + ./test.sh diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch 2022-02-23 04:07:21.000000000 +0000 @@ -1,41 +1,20 @@ -From 6bfce5dc2cbf834c74dbccb7538adc08c6eb57e7 Mon Sep 17 00:00:00 2001 +From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001 From: bjorn3 -Date: Sun, 25 Jul 2021 18:39:31 +0200 +Date: Thu, 18 Nov 2021 19:28:40 +0100 Subject: [PATCH] Disable unsupported tests --- - crates/core_simd/src/vector.rs | 2 ++ - crates/core_simd/src/math.rs | 4 ++++ - crates/core_simd/tests/masks.rs | 12 ------------ - crates/core_simd/tests/ops_macros.rs | 6 ++++++ - crates/core_simd/tests/round.rs | 2 ++ - 6 files changed, 15 insertions(+), 13 deletions(-) + crates/core_simd/src/math.rs | 6 ++++++ + crates/core_simd/src/vector.rs | 2 ++ + crates/core_simd/tests/masks.rs | 2 ++ + crates/core_simd/tests/ops_macros.rs | 4 ++++ + 4 files changed, 14 insertions(+) -diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs -index 25c5309..2b3d819 100644 ---- a/crates/core_simd/src/vector.rs -+++ b/crates/core_simd/src/vector.rs -@@ -22,6 +22,7 @@ where - self.0 - } - -+ /* - /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices. - /// If an index is out of bounds, that lane instead selects the value from the "or" vector. - /// ``` -@@ -150,6 +151,7 @@ where - // Cleared ☢️ *mut T Zone - } - } -+ */ - } - - impl Copy for Simd diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs -index 7290a28..e394730 100644 +index 2bae414..2f87499 100644 --- a/crates/core_simd/src/math.rs +++ b/crates/core_simd/src/math.rs -@@ -2,6 +2,7 @@ macro_rules! impl_uint_arith { +@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith { ($($ty:ty),+) => { $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { @@ -43,15 +22,15 @@ /// Lanewise saturating add. /// /// # Examples -@@ -38,6 +39,7 @@ macro_rules! impl_uint_arith { +@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith { pub fn saturating_sub(self, second: Self) -> Self { - unsafe { crate::intrinsics::simd_saturating_sub(self, second) } + unsafe { simd_saturating_sub(self, second) } } + */ })+ } } -@@ -46,6 +48,7 @@ macro_rules! impl_int_arith { +@@ -51,6 +53,7 @@ macro_rules! impl_int_arith { ($($ty:ty),+) => { $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { @@ -59,7 +38,23 @@ /// Lanewise saturating add. /// /// # Examples -@@ -141,6 +144,7 @@ macro_rules! impl_int_arith { +@@ -89,6 +92,7 @@ macro_rules! impl_int_arith { + pub fn saturating_sub(self, second: Self) -> Self { + unsafe { simd_saturating_sub(self, second) } + } ++ */ + + /// Lanewise absolute value, implemented in Rust. + /// Every lane becomes its absolute value. +@@ -109,6 +113,7 @@ macro_rules! impl_int_arith { + (self^m) - m + } + ++ /* + /// Lanewise saturating absolute value, implemented in Rust. + /// As abs(), except the MIN value becomes MAX instead of itself. + /// +@@ -151,6 +156,7 @@ macro_rules! impl_int_arith { pub fn saturating_neg(self) -> Self { Self::splat(0).saturating_sub(self) } @@ -67,51 +62,51 @@ })+ } } +diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs +index 7c5ec2b..c8631e8 100644 +--- a/crates/core_simd/src/vector.rs ++++ b/crates/core_simd/src/vector.rs +@@ -75,6 +75,7 @@ where + Self(array) + } + ++ /* + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// If an index is out-of-bounds, the lane is instead selected from the `or` vector. + /// +@@ -297,6 +298,7 @@ where + // Cleared ☢️ *mut T Zone + } + } ++ */ + } + + impl Copy for Simd diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs -index 61d8e44..2bccae2 100644 +index 6a8ecd3..68fcb49 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs -@@ -67,19 +67,6 @@ macro_rules! test_mask_api { - assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); +@@ -68,6 +68,7 @@ macro_rules! test_mask_api { assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); } -- -- #[cfg(feature = "generic_const_exprs")] -- #[test] -- fn roundtrip_bitmask_conversion() { -- let values = [ -- true, false, false, true, false, false, true, false, -- true, true, false, false, false, false, false, true, -- ]; -- let mask = core_simd::Mask::<$type, 16>::from_array(values); -- let bitmask = mask.to_bitmask(); -- assert_eq!(bitmask, [0b01001001, 0b10000011]); -- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); -- } + ++ /* + #[cfg(feature = "generic_const_exprs")] + #[test] + fn roundtrip_bitmask_conversion() { +@@ -80,6 +81,7 @@ macro_rules! test_mask_api { + assert_eq!(bitmask, [0b01001001, 0b10000011]); + assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); + } ++ */ } } } diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs -index cb39e73..fc0ebe1 100644 +index 31b7ee2..bd04b3c 100644 --- a/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs -@@ -435,6 +435,7 @@ macro_rules! impl_float_tests { - ) - } - -+ /* - fn mul_add() { - test_helpers::test_ternary_elementwise( - &Vector::::mul_add, -@@ -442,6 +443,7 @@ macro_rules! impl_float_tests { - &|_, _, _| true, - ) - } -+ */ - - fn recip() { - test_helpers::test_unary_elementwise( -@@ -581,6 +585,7 @@ macro_rules! impl_float_tests { +@@ -567,6 +567,7 @@ macro_rules! impl_float_tests { }); } @@ -119,7 +114,7 @@ fn horizontal_max() { test_helpers::test_1(&|x| { let vmax = Vector::::from_array(x).horizontal_max(); -@@ -604,6 +609,7 @@ macro_rules! impl_float_tests { +@@ -590,6 +591,7 @@ macro_rules! impl_float_tests { Ok(()) }); } @@ -127,26 +122,22 @@ } #[cfg(feature = "std")] -diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs -index 37044a7..4cdc6b7 100644 ---- a/crates/core_simd/tests/round.rs -+++ b/crates/core_simd/tests/round.rs -@@ -25,6 +25,7 @@ macro_rules! float_rounding_test { - ) - } - -+ /* - fn round() { - test_helpers::test_unary_elementwise( - &Vector::::round, -@@ -32,6 +33,7 @@ macro_rules! float_rounding_test { - &|_| true, - ) +@@ -604,6 +606,7 @@ macro_rules! impl_float_tests { + ) + } + ++ /* + fn mul_add() { + test_helpers::test_ternary_elementwise( + &Vector::::mul_add, +@@ -611,6 +614,7 @@ macro_rules! impl_float_tests { + &|_, _, _| true, + ) + } ++ */ } -+ */ - - fn trunc() { - test_helpers::test_unary_elementwise( + } + } -- 2.26.2.7.g19db9cfb68 diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch 2022-02-23 04:07:21.000000000 +0000 @@ -107,7 +107,7 @@ inner::monotonize(raw) } --#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))] +-#[cfg(any(all(target_has_atomic = "64", not(target_has_atomic = "128")), target_arch = "aarch64"))] +#[cfg(target_has_atomic = "64")] pub mod inner { use crate::sync::atomic::AtomicU64; @@ -117,7 +117,7 @@ } +/* - #[cfg(target_has_atomic = "128")] + #[cfg(all(target_has_atomic = "128", not(target_arch = "aarch64")))] pub mod inner { use crate::sync::atomic::AtomicU128; @@ -94,8 +95,9 @@ pub mod inner { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,30 @@ +From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Fri, 3 Dec 2021 12:16:30 +0100 +Subject: [PATCH] Disable long running tests + +--- + library/core/tests/slice.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 2c8f00a..44847ee 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut { + }; + } + ++/* + #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) + take_tests! { + slice: &[(); usize::MAX], method: take, + (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), +@@ -2345,3 +2347,4 @@ take_tests! { + (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), + } ++*/ +-- +2.26.2.7.g19db9cfb68 + diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Readme.md rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Readme.md --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Readme.md 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/Readme.md 2022-02-23 04:07:21.000000000 +0000 @@ -37,7 +37,7 @@ In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo build +$ $cg_clif_dir/build/cargo-clif build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/rust-toolchain rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/rust-toolchain --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/rust-toolchain 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/rust-toolchain 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-09-19" +channel = "nightly-2021-12-30" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,78 @@ +use std::env; +#[cfg(unix)] +use std::os::unix::process::CommandExt; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) { + eprintln!( + "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" + ); + env::remove_var("RUSTC_WRAPPER"); + } + + let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + + env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX)); + + let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new()); + rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); + rustdoc_flags.push_str( + sysroot + .join(if cfg!(windows) { "bin" } else { "lib" }) + .join( + env::consts::DLL_PREFIX.to_string() + + "rustc_codegen_cranelift" + + env::consts::DLL_SUFFIX, + ) + .to_str() + .unwrap(), + ); + rustdoc_flags.push_str(" --sysroot "); + rustdoc_flags.push_str(sysroot.to_str().unwrap()); + env::set_var("RUSTDOCFLAGS", rustdoc_flags); + + // Ensure that the right toolchain is used + env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + + let args: Vec<_> = match env::args().nth(1).as_deref() { + Some("jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + IntoIterator::into_iter(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain([ + "--".to_string(), + "-Zunstable-features".to_string(), + "-Cllvm-args=mode=jit".to_string(), + ]) + .collect() + } + Some("lazy-jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + IntoIterator::into_iter(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain([ + "--".to_string(), + "-Zunstable-features".to_string(), + "-Cllvm-args=mode=jit-lazy".to_string(), + ]) + .collect() + } + _ => env::args().skip(1).collect(), + }; + + #[cfg(unix)] + Command::new("cargo").args(args).exec(); + + #[cfg(not(unix))] + std::process::exit( + Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1), + ); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/cargo.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -use std::env; -#[cfg(unix)] -use std::os::unix::process::CommandExt; -use std::path::PathBuf; -use std::process::Command; - -fn main() { - if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) { - eprintln!( - "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" - ); - env::remove_var("RUSTC_WRAPPER"); - } - - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); - - env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX)); - - let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new()); - rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); - rustdoc_flags.push_str( - sysroot - .join(if cfg!(windows) { "bin" } else { "lib" }) - .join( - env::consts::DLL_PREFIX.to_string() - + "rustc_codegen_cranelift" - + env::consts::DLL_SUFFIX, - ) - .to_str() - .unwrap(), - ); - rustdoc_flags.push_str(" --sysroot "); - rustdoc_flags.push_str(sysroot.to_str().unwrap()); - env::set_var("RUSTDOCFLAGS", rustdoc_flags); - - // Ensure that the right toolchain is used - env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); - - let args: Vec<_> = match env::args().nth(1).as_deref() { - Some("jit") => { - env::set_var( - "RUSTFLAGS", - env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", - ); - std::array::IntoIter::new(["rustc".to_string()]) - .chain(env::args().skip(2)) - .chain([ - "--".to_string(), - "-Zunstable-features".to_string(), - "-Cllvm-args=mode=jit".to_string(), - ]) - .collect() - } - Some("lazy-jit") => { - env::set_var( - "RUSTFLAGS", - env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", - ); - std::array::IntoIter::new(["rustc".to_string()]) - .chain(env::args().skip(2)) - .chain([ - "--".to_string(), - "-Zunstable-features".to_string(), - "-Cllvm-args=mode=jit-lazy".to_string(), - ]) - .collect() - } - _ => env::args().skip(1).collect(), - }; - - #[cfg(unix)] - Command::new("cargo").args(args).exec(); - - #[cfg(not(unix))] - std::process::exit( - Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1), - ); -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/bash set -e -./y.rs build +./y.rs build --no-unstable-features source scripts/config.sh echo "[SETUP] Rust fork" @@ -33,7 +33,7 @@ [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "0.1.46", features = ['rustc-dep-of-std', 'no-asm'] } ++compiler_builtins = { version = "0.1.66", features = ['rustc-dep-of-std', 'no-asm'] } [dev-dependencies] rand = "0.7" @@ -53,5 +53,6 @@ [rust] codegen-backends = ["cranelift"] deny-warnings = false +verbose-tests = false EOF popd diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ cargo install ripgrep -rm -r src/test/ui/{extern/,panics/,unsized-locals/,thinlto/,simd*,*lto*.rs,linkage*,unwind-*.rs} || true +rm -r src/test/ui/{extern/,panics/,unsized-locals/,lto/,simd*,linkage*,unwind-*.rs} || true for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto|// needs-asm-support" src/test/ui); do rm $test done @@ -30,22 +30,25 @@ rm src/test/ui/issues/issue-26655.rs rm src/test/ui/issues/issue-29485.rs rm src/test/ui/issues/issue-30018-panic.rs -rm src/test/ui/multi-panic.rs +rm src/test/ui/process/multi-panic.rs rm src/test/ui/sepcomp/sepcomp-unwind.rs rm src/test/ui/structs-enums/unit-like-struct-drop-run.rs -rm src/test/ui/terminate-in-initializer.rs +rm src/test/ui/drop/terminate-in-initializer.rs rm src/test/ui/threads-sendsync/task-stderr.rs rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/numbers-arithmetic/issue-8460.rs -rm src/test/ui/rt-explody-panic-payloads.rs +rm src/test/ui/runtime/rt-explody-panic-payloads.rs rm src/test/incremental/change_crate_dep_kind.rs +rm src/test/ui/threads-sendsync/unwind-resource.rs rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations -rm src/test/ui/init-large-type.rs # same +rm src/test/ui/codegen/init-large-type.rs # same rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected rm src/test/ui/issues/issue-33992.rs # unsupported linkages rm src/test/ui/issues/issue-51947.rs # same +rm src/test/incremental/hashes/function_interfaces.rs # same +rm src/test/incremental/hashes/statics.rs # same rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants rm src/test/ui/mir/mir_raw_fat_ptr.rs # same @@ -59,22 +62,22 @@ rm src/test/incremental/hashes/inline_asm.rs # inline asm rm src/test/incremental/issue-72386.rs # same -rm src/test/incremental/issue-49482.rs # same -rm src/test/incremental/issue-54059.rs # same rm src/test/incremental/lto.rs # requires lto +rm src/test/incremental/dirty_clean.rs # TODO rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/ rm -r src/test/run-make/unstable-flag-required # same +rm -r src/test/run-make/rustdoc-* # same rm -r src/test/run-make/emit-named-files # requires full --emit support -rm src/test/pretty/asm.rs # inline asm -rm src/test/pretty/raw-str-nonexpr.rs # same - rm -r src/test/run-pass-valgrind/unsized-locals rm src/test/ui/json-bom-plus-crlf-multifile.rs # differing warning rm src/test/ui/json-bom-plus-crlf.rs # same +rm src/test/ui/intrinsics/const-eval-select-x86_64.rs # same rm src/test/ui/match/issue-82392.rs # differing error +rm src/test/ui/consts/min_const_fn/address_of_const.rs # same +rm src/test/ui/consts/issue-miri-1910.rs # same rm src/test/ui/type-alias-impl-trait/cross_crate_ice*.rs # requires removed aux dep rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition @@ -88,6 +91,16 @@ rm src/test/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs rm src/test/ui/abi/variadic-ffi.rs # requires callee side vararg support +rm src/test/ui/command/command-current-dir.rs # can't find libstd.so + +rm src/test/ui/abi/stack-protector.rs # requires stack protector support + +rm src/test/incremental/issue-80691-bad-eval-cache.rs # wrong exit code +rm src/test/incremental/spike-neg1.rs # errors out for some reason +rm src/test/incremental/spike-neg2.rs # same + +rm src/test/incremental/thinlto/cgu_invalidated_when_import_{added,removed}.rs # requires LLVM + echo "[TEST] rustc test suite" -RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui} +RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental} popd diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/tests.sh rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/tests.sh --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/tests.sh 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/scripts/tests.sh 2022-02-23 04:07:21.000000000 +0000 @@ -35,6 +35,10 @@ $MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE" $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers + echo "[AOT] issue_91827_extern_types" + $MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE" + $RUN_WRAPPER ./target/out/issue_91827_extern_types + echo "[AOT] alloc_system" $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" @@ -76,73 +80,73 @@ function extended_sysroot_tests() { pushd rand - ../build/cargo clean + ../build/cargo-clif clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-random/rand" - ../build/cargo test --workspace + ../build/cargo-clif test --workspace else echo "[AOT] rust-random/rand" - ../build/cargo build --workspace --target $TARGET_TRIPLE --tests + ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests fi popd pushd simple-raytracer if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \ + hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo-clif clean" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \ - "../build/cargo build" + "../build/cargo-clif build" echo "[BENCH RUN] ebobby/simple-raytracer" cp ./target/debug/main ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif else - ../build/cargo clean + ../build/cargo-clif clean echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo build --target $TARGET_TRIPLE + ../build/cargo-clif build --target $TARGET_TRIPLE echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" fi popd pushd build_sysroot/sysroot_src/library/core/tests echo "[TEST] libcore" - ../../../../../build/cargo clean + ../../../../../build/cargo-clif clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo test + ../../../../../build/cargo-clif test else - ../../../../../build/cargo build --target $TARGET_TRIPLE --tests + ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests fi popd pushd regex echo "[TEST] rust-lang/regex example shootout-regex-dna" - ../build/cargo clean + ../build/cargo-clif clean export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE + ../build/cargo-clif build --example shootout-regex-dna --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then cat examples/regexdna-input.txt \ - | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | ../build/cargo-clif run --example shootout-regex-dna --target $TARGET_TRIPLE \ | grep -v "Spawned thread" > res.txt diff -u res.txt examples/regexdna-output.txt fi if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-lang/regex tests" - ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + ../build/cargo-clif test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q else echo "[AOT] rust-lang/regex tests" - ../build/cargo build --tests --target $TARGET_TRIPLE + ../build/cargo-clif build --tests --target $TARGET_TRIPLE fi popd pushd portable-simd echo "[TEST] rust-lang/portable-simd" - ../build/cargo clean - ../build/cargo build --all-targets --target $TARGET_TRIPLE + ../build/cargo-clif clean + ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../build/cargo test -q + ../build/cargo-clif test -q fi popd } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,11 +18,11 @@ fn clif_sig_from_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, - triple: &target_lexicon::Triple, + default_call_conv: CallConv, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> Signature { let call_conv = match fn_abi.conv { - Conv::Rust | Conv::C => CallConv::triple_default(triple), + Conv::Rust | Conv::C => default_call_conv, Conv::X86_64SysV => CallConv::SystemV, Conv::X86_64Win64 => CallConv::WindowsFastcall, Conv::ArmAapcs @@ -55,7 +55,7 @@ assert!(!inst.substs.needs_infer()); clif_sig_from_fn_abi( tcx, - triple, + CallConv::triple_default(triple), &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), ) } @@ -91,7 +91,7 @@ returns: Vec, args: &[Value], ) -> &[Value] { - let sig = Signature { params, returns, call_conv: CallConv::triple_default(self.triple()) }; + let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); let call_inst = self.bcx.ins().call(func_ref, args); @@ -420,7 +420,7 @@ } let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0].value, idx); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); (CallTarget::Indirect(sig, method), Some(ptr)) @@ -440,7 +440,7 @@ } let func = codegen_operand(fx, func).load_scalar(fx); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); (CallTarget::Indirect(sig, func), None) @@ -531,7 +531,7 @@ let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs 2022-02-23 04:07:21.000000000 +0000 @@ -71,7 +71,7 @@ .prefix .iter() .flatten() - .map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size })) + .map(|®| reg_to_abi_param(reg)) .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) .collect::>(); @@ -117,7 +117,9 @@ PassMode::Cast(cast) => cast_target_to_abi_params(cast), PassMode::Indirect { attrs, extra_attrs: None, on_stack } => { if on_stack { - let size = u32::try_from(self.layout.size.bytes()).unwrap(); + // Abi requires aligning struct size to pointer size + let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); + let size = u32::try_from(size.bytes()).unwrap(); smallvec![apply_arg_attrs_to_abi_param( AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), attrs @@ -204,7 +206,6 @@ // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, - offset: None, }); let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); let mut offset = 0; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/archive.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/archive.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/archive.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/archive.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,6 @@ //! Creation of ar archives like for the lib and staticlib crate type use std::collections::BTreeMap; -use std::convert::TryFrom; use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; @@ -10,7 +9,7 @@ use rustc_session::Session; use object::read::archive::ArchiveFile; -use object::{Object, ObjectSymbol, ReadCache, SymbolKind}; +use object::{Object, ObjectSymbol, ReadCache}; #[derive(Debug)] enum ArchiveEntry { @@ -150,12 +149,7 @@ object .symbols() .filter_map(|symbol| { - if symbol.is_undefined() - || symbol.is_local() - || symbol.kind() != SymbolKind::Data - && symbol.kind() != SymbolKind::Text - && symbol.kind() != SymbolKind::Tls - { + if symbol.is_undefined() || symbol.is_local() { None } else { symbol.name().map(|name| name.as_bytes().to_vec()).ok() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/base.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,7 @@ //! Codegen of a single function use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; +use rustc_ast::InlineAsmOptions; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; @@ -48,13 +49,15 @@ (0..mir.basic_blocks().len()).map(|_| bcx.create_block()).collect(); // Make FunctionCx - let pointer_type = module.target_config().pointer_type(); + let target_config = module.target_config(); + let pointer_type = target_config.pointer_type(); let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); let mut fx = FunctionCx { cx, module, tcx, + target_config, pointer_type, constants_cx: ConstantCx::new(), @@ -71,8 +74,6 @@ clif_comments, source_info_set: indexmap::IndexSet::new(), next_ssa_var: 0, - - inline_asm_index: 0, }; let arg_uninhabited = fx @@ -203,7 +204,6 @@ tcx.sess.err(&format!("{:?}", err)); let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error( &func, - None, Some(Box::new(writer)), err, ); @@ -239,7 +239,8 @@ fx.add_comment(inst, terminator_head); } - fx.set_debug_loc(bb_data.terminator().source_info); + let source_info = bb_data.terminator().source_info; + fx.set_debug_loc(source_info); match &bb_data.terminator().kind { TerminatorKind::Goto { target } => { @@ -294,20 +295,18 @@ AssertKind::BoundsCheck { ref len, ref index } => { let len = codegen_operand(fx, len).load_scalar(fx); let index = codegen_operand(fx, index).load_scalar(fx); - let location = fx - .get_caller_location(bb_data.terminator().source_info.span) - .load_scalar(fx); + let location = fx.get_caller_location(source_info.span).load_scalar(fx); codegen_panic_inner( fx, rustc_hir::LangItem::PanicBoundsCheck, &[index, len, location], - bb_data.terminator().source_info.span, + source_info.span, ); } _ => { let msg_str = msg.description(); - codegen_panic(fx, msg_str, bb_data.terminator().source_info.span); + codegen_panic(fx, msg_str, source_info.span); } } } @@ -378,10 +377,18 @@ options, destination, line_spans: _, + cleanup: _, } => { + if options.contains(InlineAsmOptions::MAY_UNWIND) { + fx.tcx.sess.span_fatal( + source_info.span, + "cranelift doesn't support unwinding from inline assembly.", + ); + } + crate::inline_asm::codegen_inline_asm( fx, - bb_data.terminator().source_info.span, + source_info.span, template, operands, *options, @@ -415,7 +422,7 @@ } TerminatorKind::Drop { place, target, unwind: _ } => { let drop_place = codegen_place(fx, *place); - crate::abi::codegen_drop(fx, bb_data.terminator().source_info.span, drop_place); + crate::abi::codegen_drop(fx, source_info.span, drop_place); let target_block = fx.get_block(*target); fx.bcx.ins().jump(target_block, &[]); @@ -671,7 +678,7 @@ // FIXME use emit_small_memset where possible let addr = lval.to_ptr().get_addr(fx); let val = operand.load_scalar(fx); - fx.bcx.call_memset(fx.module.target_config(), addr, val, times); + fx.bcx.call_memset(fx.target_config, addr, val, times); } else { let loop_block = fx.bcx.create_block(); let loop_block2 = fx.bcx.create_block(); @@ -708,30 +715,6 @@ let operand = operand.load_scalar(fx); lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } - Rvalue::NullaryOp(NullOp::Box, content_ty) => { - let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap(); - let content_ty = fx.monomorphize(content_ty); - let layout = fx.layout_of(content_ty); - let llsize = fx.bcx.ins().iconst(usize_type, layout.size.bytes() as i64); - let llalign = fx.bcx.ins().iconst(usize_type, layout.align.abi.bytes() as i64); - let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty)); - - // Allocate space: - let def_id = - match fx.tcx.lang_items().require(rustc_hir::LangItem::ExchangeMalloc) { - Ok(id) => id, - Err(s) => { - fx.tcx - .sess - .fatal(&format!("allocation of `{}` {}", box_layout.ty, s)); - } - }; - let instance = ty::Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); - let func_ref = fx.get_function_ref(instance); - let call = fx.bcx.ins().call(func_ref, &[llsize, llalign]); - let ptr = fx.bcx.inst_results(call)[0]; - lval.write_cvalue(fx, CValue::by_val(ptr, box_layout)); - } Rvalue::NullaryOp(null_op, ty) => { assert!( lval.layout() @@ -742,10 +725,8 @@ let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), - NullOp::Box => unreachable!(), }; - let val = - CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); + let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); lval.write_cvalue(fx, val); } Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { @@ -793,7 +774,7 @@ let elem_size: u64 = pointee.size.bytes(); let bytes = if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, bytes); + fx.bcx.call_memcpy(fx.target_config, dst, src, bytes); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/common.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/common.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/common.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/common.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,4 @@ +use cranelift_codegen::isa::TargetFrontendConfig; use rustc_index::vec::IndexVec; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, @@ -235,7 +236,8 @@ pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>, pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, - pub(crate) pointer_type: Type, // Cached from module + pub(crate) target_config: TargetFrontendConfig, // Cached from module + pub(crate) pointer_type: Type, // Cached from module pub(crate) constants_cx: ConstantCx, pub(crate) instance: Instance<'tcx>, @@ -255,8 +257,6 @@ /// This should only be accessed by `CPlace::new_var`. pub(crate) next_ssa_var: u32, - - pub(crate) inline_asm_index: u32, } impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { @@ -359,10 +359,6 @@ crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty()) } - pub(crate) fn triple(&self) -> &target_lexicon::Triple { - self.module.isa().triple() - } - pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value { let mut data_ctx = DataContext::new(); data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice()); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/constant.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/constant.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/constant.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/constant.rs 2022-02-23 04:07:21.000000000 +0000 @@ -369,7 +369,7 @@ TodoItem::Static(def_id) => { //println!("static {:?}", def_id); - let section_name = tcx.codegen_fn_attrs(def_id).link_section.map(|s| s.as_str()); + let section_name = tcx.codegen_fn_attrs(def_id).link_section; let alloc = tcx.eval_static_initializer(def_id).unwrap(); @@ -388,6 +388,7 @@ if let Some(section_name) = section_name { let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let section_name = section_name.as_str(); if let Some(names) = section_name.split_once(',') { names } else { @@ -397,7 +398,7 @@ )); } } else { - ("", &*section_name) + ("", section_name.as_str()) }; data_ctx.set_segment_section(segment_name, section_name); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -67,10 +67,8 @@ } /// Perform the collected relocations to be usable for JIT usage. - #[cfg(feature = "jit")] + #[cfg(all(feature = "jit", not(windows)))] pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec { - use std::convert::TryInto; - for reloc in self.relocs.drain(..) { match reloc.name { super::DebugRelocName::Section(_) => unreachable!(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ use rustc_index::vec::IndexVec; use cranelift_codegen::entity::EntityRef; -use cranelift_codegen::ir::{LabelValueLoc, StackSlots, ValueLabel, ValueLoc}; +use cranelift_codegen::ir::{Endianness, LabelValueLoc, ValueLabel}; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::ValueLocRange; @@ -23,15 +23,6 @@ pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; -fn target_endian(tcx: TyCtxt<'_>) -> RunTimeEndian { - use rustc_target::abi::Endian; - - match tcx.data_layout.endian { - Endian::Big => RunTimeEndian::Big, - Endian::Little => RunTimeEndian::Little, - } -} - pub(crate) struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -60,6 +51,11 @@ address_size: isa.frontend_config().pointer_bytes(), }; + let endian = match isa.endianness() { + Endianness::Little => RunTimeEndian::Little, + Endianness::Big => RunTimeEndian::Big, + }; + let mut dwarf = DwarfUnit::new(encoding); let producer = format!( @@ -67,7 +63,12 @@ rustc_interface::util::version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ); - let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped).into_owned(); + let comp_dir = tcx + .sess + .opts + .working_dir + .to_string_lossy(FileNameDisplayPreference::Remapped) + .into_owned(); let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { Some(path) => { let name = path.to_string_lossy().into_owned(); @@ -103,7 +104,7 @@ DebugContext { tcx, - endian: target_endian(tcx), + endian, dwarf, unit_range_list: RangeList(Vec::new()), @@ -250,7 +251,7 @@ // FIXME make it more reliable and implement scopes before re-enabling this. if false { - let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); + let value_labels_ranges = std::collections::HashMap::new(); // FIXME for (local, _local_decl) in mir.local_decls.iter_enumerated() { let ty = self.tcx.subst_and_normalize_erasing_regions( @@ -264,7 +265,6 @@ self, isa, symbol, - context, &local_map, &value_labels_ranges, Place { local, projection: ty::List::empty() }, @@ -283,7 +283,6 @@ debug_context: &mut DebugContext<'tcx>, isa: &dyn TargetIsa, symbol: usize, - context: &Context, local_map: &IndexVec>, #[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap< ValueLabel, @@ -306,12 +305,7 @@ addend: i64::from(value_loc_range.start), }, end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) }, - data: translate_loc( - isa, - value_loc_range.loc, - &context.func.stack_slots, - ) - .unwrap(), + data: translate_loc(isa, value_loc_range.loc).unwrap(), }) .collect(), ); @@ -340,34 +334,14 @@ AttributeValue::Exprloc(Expression::new()) // For PointerBase::Stack: - //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap()) + //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot)).unwrap()) } } } // Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137 -fn translate_loc( - isa: &dyn TargetIsa, - loc: LabelValueLoc, - stack_slots: &StackSlots, -) -> Option { +fn translate_loc(isa: &dyn TargetIsa, loc: LabelValueLoc) -> Option { match loc { - LabelValueLoc::ValueLoc(ValueLoc::Reg(reg)) => { - let machine_reg = isa.map_dwarf_register(reg).unwrap(); - let mut expr = Expression::new(); - expr.op_reg(gimli::Register(machine_reg)); - Some(expr) - } - LabelValueLoc::ValueLoc(ValueLoc::Stack(ss)) => { - if let Some(ss_offset) = stack_slots[ss].offset { - let mut expr = Expression::new(); - expr.op_breg(X86_64::RBP, i64::from(ss_offset) + 16); - Some(expr) - } else { - None - } - } - LabelValueLoc::ValueLoc(ValueLoc::Unassigned) => unreachable!(), LabelValueLoc::Reg(reg) => { let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap(); let mut expr = Expression::new(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,3 @@ -use std::convert::{TryFrom, TryInto}; - use rustc_data_structures::fx::FxHashMap; use cranelift_module::FuncId; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,6 +2,7 @@ use crate::prelude::*; +use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa}; use cranelift_object::ObjectProduct; @@ -17,8 +18,11 @@ } impl UnwindContext { - pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self { - let endian = super::target_endian(tcx); + pub(crate) fn new(isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self { + let endian = match isa.endianness() { + Endianness::Little => RunTimeEndian::Little, + Endianness::Big => RunTimeEndian::Big, + }; let mut frame_table = FrameTable::default(); let cie_id = if let Some(mut cie) = isa.create_systemv_cie() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,6 +4,7 @@ use std::path::PathBuf; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_metadata::EncodedMetadata; @@ -84,7 +85,7 @@ let work_product = cgu.work_product(tcx); if let Some(saved_file) = &work_product.saved_file { let obj_out = - tcx.output_filenames(()).temp_path(OutputType::Object, Some(&cgu.name().as_str())); + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); object = Some(obj_out.clone()); let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &saved_file); if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { @@ -123,6 +124,7 @@ backend_config.clone(), module.isa(), tcx.sess.opts.debuginfo != DebugInfo::None, + cgu_name, ); super::predefine_mono_items(tcx, &mut module, &mono_items); for (mono_item, _) in mono_items { @@ -176,7 +178,7 @@ ) }); - codegen_global_asm(tcx, &cgu.name().as_str(), &cx.global_asm); + codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); codegen_result } @@ -207,7 +209,7 @@ cgus.iter() .map(|cgu| { let cgu_reuse = determine_cgu_reuse(tcx, cgu); - tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); + tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); match cgu_reuse { _ if backend_config.disable_incr_cache => {} @@ -241,7 +243,7 @@ let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); - let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true); + let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true); let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); @@ -277,7 +279,8 @@ let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); - let obj = crate::metadata::new_metadata_object(tcx, &metadata_cgu_name, &metadata); + let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); + let obj = create_compressed_metadata_file(tcx.sess, &metadata, &symbol_name); if let Err(err) = std::fs::write(&tmp_file, obj) { tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,7 @@ use std::cell::RefCell; use std::ffi::CString; -use std::lazy::{Lazy, SyncOnceCell}; +use std::lazy::SyncOnceCell; use std::os::raw::{c_char, c_int}; use std::sync::{mpsc, Mutex}; @@ -11,6 +11,7 @@ use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; +use rustc_span::Symbol; use cranelift_jit::{JITBuilder, JITModule}; @@ -23,7 +24,7 @@ } thread_local! { - static LAZY_JIT_STATE: RefCell> = RefCell::new(None); + static LAZY_JIT_STATE: RefCell> = const { RefCell::new(None) }; } /// The Sender owned by the rustc thread @@ -50,12 +51,11 @@ fn send(self) -> Result<(), mpsc::SendError> { thread_local! { /// The Sender owned by the local thread - static LOCAL_MESSAGE_SENDER: Lazy> = Lazy::new(|| + static LOCAL_MESSAGE_SENDER: mpsc::Sender = GLOBAL_MESSAGE_SENDER .get().unwrap() .lock().unwrap() - .clone() - ); + .clone(); } LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self)) } @@ -76,7 +76,13 @@ jit_builder.symbols(imported_symbols); let mut jit_module = JITModule::new(jit_builder); - let mut cx = crate::CodegenCx::new(tcx, backend_config.clone(), jit_module.isa(), false); + let mut cx = crate::CodegenCx::new( + tcx, + backend_config.clone(), + jit_module.isa(), + false, + Symbol::intern("dummy_cgu_name"), + ); crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context); crate::main_shim::maybe_create_entry_wrapper( @@ -246,7 +252,13 @@ jit_module.prepare_for_function_redefine(func_id).unwrap(); - let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false); + let mut cx = crate::CodegenCx::new( + tcx, + backend_config, + jit_module.isa(), + false, + Symbol::intern("dummy_cgu_name"), + ); tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, jit_module, instance)); assert!(cx.global_asm.is_empty()); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,4 @@ -//! Codegen of [`asm!`] invocations. +//! Codegen of `asm!` invocations. use crate::prelude::*; @@ -6,6 +6,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::InlineAsmOperand; +use rustc_span::Symbol; use rustc_target::asm::*; pub(crate) fn codegen_inline_asm<'tcx>( @@ -17,10 +18,7 @@ ) { // FIXME add .eh_frame unwind info directives - if template.is_empty() { - // Black box - return; - } else if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { let true_ = fx.bcx.ins().iconst(types::I32, 1); fx.bcx.ins().trapnz(true_, TrapCode::User(1)); return; @@ -41,8 +39,10 @@ assert_eq!(operands.len(), 4); let (leaf, eax_place) = match operands[1] { InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::ax)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)) + ); ( crate::base::codegen_operand(fx, in_value).load_scalar(fx), crate::base::codegen_place(fx, out_place.unwrap()), @@ -64,8 +64,10 @@ }; let (sub_leaf, ecx_place) = match operands[2] { InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::cx)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)) + ); ( crate::base::codegen_operand(fx, in_value).load_scalar(fx), crate::base::codegen_place(fx, out_place.unwrap()), @@ -75,8 +77,10 @@ }; let edx_place = match operands[3] { InlineAsmOperand::Out { reg, late: true, place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::dx)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)) + ); crate::base::codegen_place(fx, place.unwrap()) } _ => unreachable!(), @@ -96,60 +100,59 @@ crate::trap::trap_unimplemented(fx, "Alloca is not supported"); } - let mut slot_size = Size::from_bytes(0); - let mut clobbered_regs = Vec::new(); let mut inputs = Vec::new(); let mut outputs = Vec::new(); - let mut new_slot = |reg_class: InlineAsmRegClass| { - let reg_size = reg_class - .supported_types(InlineAsmArch::X86_64) - .iter() - .map(|(ty, _)| ty.size()) - .max() - .unwrap(); - let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); - slot_size = slot_size.align_to(align); - let offset = slot_size; - slot_size += reg_size; - offset + let mut asm_gen = InlineAssemblyGenerator { + tcx: fx.tcx, + arch: fx.tcx.sess.asm_arch.unwrap(), + template, + operands, + options, + registers: Vec::new(), + stack_slots_clobber: Vec::new(), + stack_slots_input: Vec::new(), + stack_slots_output: Vec::new(), + stack_slot_size: Size::from_bytes(0), }; + asm_gen.allocate_registers(); + asm_gen.allocate_stack_slots(); + + let inline_asm_index = fx.cx.inline_asm_index.get(); + fx.cx.inline_asm_index.set(inline_asm_index + 1); + let asm_name = format!( + "__inline_asm_{}_n{}", + fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + inline_asm_index + ); + + let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); + fx.cx.global_asm.push_str(&generated_asm); - // FIXME overlap input and output slots to save stack space - for operand in operands { + for (i, operand) in operands.iter().enumerate() { match *operand { - InlineAsmOperand::In { reg, ref value } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::In { reg: _, ref value } => { inputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_input[i].unwrap(), crate::base::codegen_operand(fx, value).load_scalar(fx), )); } - InlineAsmOperand::Out { reg, late: _, place } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { outputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_output[i].unwrap(), crate::base::codegen_place(fx, place), )); } } - InlineAsmOperand::InOut { reg, late: _, ref in_value, out_place } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => { inputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_input[i].unwrap(), crate::base::codegen_operand(fx, in_value).load_scalar(fx), )); if let Some(out_place) = out_place { outputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_output[i].unwrap(), crate::base::codegen_place(fx, out_place), )); } @@ -160,110 +163,474 @@ } } - let inline_asm_index = fx.inline_asm_index; - fx.inline_asm_index += 1; - let asm_name = format!("{}__inline_asm_{}", fx.symbol_name, inline_asm_index); - - let generated_asm = generate_asm_wrapper( - &asm_name, - InlineAsmArch::X86_64, - options, - template, - clobbered_regs, - &inputs, - &outputs, - ); - fx.cx.global_asm.push_str(&generated_asm); - - call_inline_asm(fx, &asm_name, slot_size, inputs, outputs); + call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); } -fn generate_asm_wrapper( - asm_name: &str, +struct InlineAssemblyGenerator<'a, 'tcx> { + tcx: TyCtxt<'tcx>, arch: InlineAsmArch, + template: &'a [InlineAsmTemplatePiece], + operands: &'a [InlineAsmOperand<'tcx>], options: InlineAsmOptions, - template: &[InlineAsmTemplatePiece], - clobbered_regs: Vec<(InlineAsmReg, Size)>, - inputs: &[(InlineAsmReg, Size, Value)], - outputs: &[(InlineAsmReg, Size, CPlace<'_>)], -) -> String { - let mut generated_asm = String::new(); - writeln!(generated_asm, ".globl {}", asm_name).unwrap(); - writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); - writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); - writeln!(generated_asm, "{}:", asm_name).unwrap(); + registers: Vec>, + stack_slots_clobber: Vec>, + stack_slots_input: Vec>, + stack_slots_output: Vec>, + stack_slot_size: Size, +} + +impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { + fn allocate_registers(&mut self) { + let sess = self.tcx.sess; + let map = allocatable_registers( + self.arch, + |feature| sess.target_features.contains(&Symbol::intern(feature)), + &sess.target, + ); + let mut allocated = FxHashMap::<_, (bool, bool)>::default(); + let mut regs = vec![None; self.operands.len()]; + + // Add explicit registers to the allocated set. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + regs[i] = Some(reg); + allocated.entry(reg).or_default().0 = true; + } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(reg), late: true, .. + } => { + regs[i] = Some(reg); + allocated.entry(reg).or_default().1 = true; + } + InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. } + | InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + regs[i] = Some(reg); + allocated.insert(reg, (true, true)); + } + _ => (), + } + } - generated_asm.push_str(".intel_syntax noprefix\n"); - generated_asm.push_str(" push rbp\n"); - generated_asm.push_str(" mov rbp,rdi\n"); + // Allocate out/inout/inlateout registers first because they are more constrained. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(class), + late: false, + .. + } + | InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::RegClass(class), .. + } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.contains_key(&r) { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.insert(reg, (true, true)); + } + _ => (), + } + } - // Save clobbered registers - if !options.contains(InlineAsmOptions::NORETURN) { - // FIXME skip registers saved by the calling convention - for &(reg, offset) in &clobbered_regs { - save_register(&mut generated_asm, arch, reg, offset); + // Allocate in/lateout. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.get(&r).copied().unwrap_or_default().0 { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.entry(reg).or_default().0 = true; + } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(class), + late: true, + .. + } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.get(&r).copied().unwrap_or_default().1 { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.entry(reg).or_default().1 = true; + } + _ => (), + } } - } - // Write input registers - for &(reg, offset, _value) in inputs { - restore_register(&mut generated_asm, arch, reg, offset); + self.registers = regs; } - if options.contains(InlineAsmOptions::ATT_SYNTAX) { - generated_asm.push_str(".att_syntax\n"); - } + fn allocate_stack_slots(&mut self) { + let mut slot_size = Size::from_bytes(0); + let mut slots_clobber = vec![None; self.operands.len()]; + let mut slots_input = vec![None; self.operands.len()]; + let mut slots_output = vec![None; self.operands.len()]; + + let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| { + let reg_size = + reg_class.supported_types(self.arch).iter().map(|(ty, _)| ty.size()).max().unwrap(); + let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); + let offset = slot_size.align_to(align); + *slot_size = offset + reg_size; + offset + }; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for saving clobbered registers + let abi_clobber = InlineAsmClobberAbi::parse( + self.arch, + |feature| self.tcx.sess.target_features.contains(&Symbol::intern(feature)), + &self.tcx.sess.target, + Symbol::intern("C"), + ) + .unwrap() + .clobbered_regs(); + for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { + let mut need_save = true; + // If the register overlaps with a register clobbered by function call, then + // we don't need to save it. + for r in abi_clobber { + r.overlapping_regs(|r| { + if r == reg { + need_save = false; + } + }); + + if !need_save { + break; + } + } - // The actual inline asm - for piece in template { - match piece { - InlineAsmTemplatePiece::String(s) => { - generated_asm.push_str(s); + if need_save { + slots_clobber[i] = Some(new_slot(reg.reg_class())); } - InlineAsmTemplatePiece::Placeholder { operand_idx: _, modifier: _, span: _ } => todo!(), } + + // Allocate stack slots for inout + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => { + let slot = new_slot(reg.reg_class()); + slots_input[i] = Some(slot); + slots_output[i] = Some(slot); + } + _ => (), + } + } + + let slot_size_before_input = slot_size; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for input + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg, .. } + | InlineAsmOperand::InOut { reg, out_place: None, .. } => { + slots_input[i] = Some(new_slot(reg.reg_class())); + } + _ => (), + } + } + + // Reset slot size to before input so that input and output operands can overlap + // and save some memory. + let slot_size_after_input = slot_size; + slot_size = slot_size_before_input; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for output + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::Out { reg, place: Some(_), .. } => { + slots_output[i] = Some(new_slot(reg.reg_class())); + } + _ => (), + } + } + + slot_size = slot_size.max(slot_size_after_input); + + self.stack_slots_clobber = slots_clobber; + self.stack_slots_input = slots_input; + self.stack_slots_output = slots_output; + self.stack_slot_size = slot_size; } - generated_asm.push('\n'); - if options.contains(InlineAsmOptions::ATT_SYNTAX) { - generated_asm.push_str(".intel_syntax noprefix\n"); + fn generate_asm_wrapper(&self, asm_name: &str) -> String { + let mut generated_asm = String::new(); + writeln!(generated_asm, ".globl {}", asm_name).unwrap(); + writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); + writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); + writeln!(generated_asm, "{}:", asm_name).unwrap(); + + let is_x86 = matches!(self.arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); + + if is_x86 { + generated_asm.push_str(".intel_syntax noprefix\n"); + } + Self::prologue(&mut generated_asm, self.arch); + + // Save clobbered registers + if !self.options.contains(InlineAsmOptions::NORETURN) { + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_clobber.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::save_register(&mut generated_asm, self.arch, reg, slot); + } + } + + // Write input registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_input.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push_str(".att_syntax\n"); + } + + // The actual inline asm + for piece in self.template { + match piece { + InlineAsmTemplatePiece::String(s) => { + generated_asm.push_str(s); + } + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => { + if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push('%'); + } + self.registers[*operand_idx] + .unwrap() + .emit(&mut generated_asm, self.arch, *modifier) + .unwrap(); + } + } + } + generated_asm.push('\n'); + + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push_str(".intel_syntax noprefix\n"); + } + + if !self.options.contains(InlineAsmOptions::NORETURN) { + // Read output registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_output.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::save_register(&mut generated_asm, self.arch, reg, slot); + } + + // Restore clobbered registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_clobber.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + + Self::epilogue(&mut generated_asm, self.arch); + } else { + Self::epilogue_noreturn(&mut generated_asm, self.arch); + } + + if is_x86 { + generated_asm.push_str(".att_syntax\n"); + } + writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); + generated_asm.push_str(".text\n"); + generated_asm.push_str("\n\n"); + + generated_asm } - if !options.contains(InlineAsmOptions::NORETURN) { - // Read output registers - for &(reg, offset, _place) in outputs { - save_register(&mut generated_asm, arch, reg, offset); + fn prologue(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" push ebp\n"); + generated_asm.push_str(" mov ebp,[esp+8]\n"); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" push rbp\n"); + generated_asm.push_str(" mov rbp,rdi\n"); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" addi sp, sp, -8\n"); + generated_asm.push_str(" sw ra, 4(sp)\n"); + generated_asm.push_str(" sw s0, 0(sp)\n"); + generated_asm.push_str(" mv s0, a0\n"); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" addi sp, sp, -16\n"); + generated_asm.push_str(" sd ra, 8(sp)\n"); + generated_asm.push_str(" sd s0, 0(sp)\n"); + generated_asm.push_str(" mv s0, a0\n"); + } + _ => unimplemented!("prologue for {:?}", arch), } + } - // Restore clobbered registers - for &(reg, offset) in clobbered_regs.iter().rev() { - restore_register(&mut generated_asm, arch, reg, offset); + fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" pop ebp\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" pop rbp\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" lw s0, 0(sp)\n"); + generated_asm.push_str(" lw ra, 4(sp)\n"); + generated_asm.push_str(" addi sp, sp, 8\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld s0, 0(sp)\n"); + generated_asm.push_str(" ld ra, 8(sp)\n"); + generated_asm.push_str(" addi sp, sp, 16\n"); + generated_asm.push_str(" ret\n"); + } + _ => unimplemented!("epilogue for {:?}", arch), } + } - generated_asm.push_str(" pop rbp\n"); - generated_asm.push_str(" ret\n"); - } else { - generated_asm.push_str(" ud2\n"); + fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 | InlineAsmArch::X86_64 => { + generated_asm.push_str(" ud2\n"); + } + InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ebreak\n"); + } + _ => unimplemented!("epilogue_noreturn for {:?}", arch), + } } - generated_asm.push_str(".att_syntax\n"); - writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); - generated_asm.push_str(".text\n"); - generated_asm.push_str("\n\n"); + fn save_register( + generated_asm: &mut String, + arch: InlineAsmArch, + reg: InlineAsmReg, + offset: Size, + ) { + match arch { + InlineAsmArch::X86 => { + write!(generated_asm, " mov [ebp+0x{:x}], ", offset.bytes()).unwrap(); + reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); + generated_asm.push('\n'); + } + InlineAsmArch::X86_64 => { + write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap(); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + generated_asm.push('\n'); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" sw "); + reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" sd "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + _ => unimplemented!("save_register for {:?}", arch), + } + } - generated_asm + fn restore_register( + generated_asm: &mut String, + arch: InlineAsmArch, + reg: InlineAsmReg, + offset: Size, + ) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" mov "); + reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); + writeln!(generated_asm, ", [ebp+0x{:x}]", offset.bytes()).unwrap(); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" mov "); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" lw "); + reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + _ => unimplemented!("restore_register for {:?}", arch), + } + } } fn call_inline_asm<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, asm_name: &str, slot_size: Size, - inputs: Vec<(InlineAsmReg, Size, Value)>, - outputs: Vec<(InlineAsmReg, Size, CPlace<'tcx>)>, + inputs: Vec<(Size, Value)>, + outputs: Vec<(Size, CPlace<'tcx>)>, ) { let stack_slot = fx.bcx.func.create_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, - offset: None, size: u32::try_from(slot_size.bytes()).unwrap(), }); if fx.clif_comments.enabled() { @@ -287,50 +654,16 @@ fx.add_comment(inline_asm_func, asm_name); } - for (_reg, offset, value) in inputs { + for (offset, value) in inputs { fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); } let stack_slot_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0); fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); - for (_reg, offset, place) in outputs { + for (offset, place) in outputs { let ty = fx.clif_type(place.layout().ty).unwrap(); let value = fx.bcx.ins().stack_load(ty, stack_slot, i32::try_from(offset.bytes()).unwrap()); place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } - -fn expect_reg(reg_or_class: InlineAsmRegOrRegClass) -> InlineAsmReg { - match reg_or_class { - InlineAsmRegOrRegClass::Reg(reg) => reg, - InlineAsmRegOrRegClass::RegClass(class) => unimplemented!("{:?}", class), - } -} - -fn save_register(generated_asm: &mut String, arch: InlineAsmArch, reg: InlineAsmReg, offset: Size) { - match arch { - InlineAsmArch::X86_64 => { - write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap(); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); - generated_asm.push('\n'); - } - _ => unimplemented!("save_register for {:?}", arch), - } -} - -fn restore_register( - generated_asm: &mut String, - arch: InlineAsmArch, - reg: InlineAsmReg, - offset: Size, -) { - match arch { - InlineAsmArch::X86_64 => { - generated_asm.push_str(" mov "); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); - writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap(); - } - _ => unimplemented!("restore_register for {:?}", arch), - } -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -503,10 +503,10 @@ if intrinsic == sym::copy_nonoverlapping { // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); } else { // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } }; // NOTE: the volatile variants have src and dst swapped @@ -522,10 +522,10 @@ // FIXME make the copy actually volatile when using emit_small_mem{cpy,move} if intrinsic == sym::volatile_copy_nonoverlapping_memory { // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); } else { // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } }; size_of_val, (c ptr) { @@ -673,7 +673,7 @@ let dst_ptr = dst.load_scalar(fx); // FIXME make the memset actually volatile when switching to emit_small_memset // FIXME use emit_small_memset - fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count); + fx.bcx.call_memset(fx.target_config, dst_ptr, val, count); }; ctlz | ctlz_nonzero, (v arg) { // FIXME trap on `ctlz_nonzero` with zero arg. @@ -1067,7 +1067,7 @@ kw.Try, (v f, v data, v _catch_fn) { // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { - call_conv: CallConv::triple_default(fx.triple()), + call_conv: fx.target_config.default_call_conv, params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))], returns: vec![], }); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs 2022-02-23 04:07:21.000000000 +0000 @@ -67,7 +67,34 @@ _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) { validate_simd_type!(fx, intrinsic, span, x.layout().ty); - let n: u16 = intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap(); + // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. + // If there is no suffix, use the index array length. + let n: u16 = if intrinsic == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + match idx_ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }).try_into().unwrap() + } + _ => { + fx.tcx.sess.span_err( + span, + &format!( + "simd_shuffle index must be an array of `u32`, got `{}`", + idx_ty, + ), + ); + // Prevent verifier error + crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + return; + } + } + } else { + intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() + }; assert_eq!(x.layout(), y.layout()); let layout = x.layout(); @@ -378,27 +405,27 @@ }; simd_reduce_min, (c v) { - // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { - let lt = fx.bcx.ins().icmp(if layout.ty.is_signed() { - IntCC::SignedLessThan - } else { - IntCC::UnsignedLessThan - }, a, b); + let lt = match layout.ty.kind() { + ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b), + ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b), + ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b), + _ => unreachable!(), + }; fx.bcx.ins().select(lt, a, b) }); }; simd_reduce_max, (c v) { - // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { - let gt = fx.bcx.ins().icmp(if layout.ty.is_signed() { - IntCC::SignedGreaterThan - } else { - IntCC::UnsignedGreaterThan - }, a, b); + let gt = match layout.ty.kind() { + ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b), + ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b), + ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b), + _ => unreachable!(), + }; fx.bcx.ins().select(gt, a, b) }); }; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,6 @@ #![warn(unused_lifetimes)] #![warn(unreachable_pub)] -extern crate snap; #[macro_use] extern crate rustc_middle; extern crate rustc_ast; @@ -26,6 +25,7 @@ extern crate rustc_driver; use std::any::Any; +use std::cell::Cell; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -34,6 +34,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::config::OutputFilenames; use rustc_session::Session; +use rustc_span::Symbol; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; @@ -59,7 +60,6 @@ mod intrinsics; mod linkage; mod main_shim; -mod metadata; mod num; mod optimize; mod pointer; @@ -71,9 +71,7 @@ mod vtable; mod prelude { - pub(crate) use std::convert::{TryFrom, TryInto}; - - pub(crate) use rustc_span::{Span, FileNameDisplayPreference}; + pub(crate) use rustc_span::{FileNameDisplayPreference, Span}; pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub(crate) use rustc_middle::bug; @@ -125,9 +123,11 @@ struct CodegenCx<'tcx> { tcx: TyCtxt<'tcx>, global_asm: String, + inline_asm_index: Cell, cached_context: Context, debug_context: Option>, unwind_context: UnwindContext, + cgu_name: Symbol, } impl<'tcx> CodegenCx<'tcx> { @@ -136,18 +136,21 @@ backend_config: BackendConfig, isa: &dyn TargetIsa, debug_info: bool, + cgu_name: Symbol, ) -> Self { assert_eq!(pointer_ty(tcx), isa.pointer_type()); let unwind_context = - UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); + UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None }; CodegenCx { tcx, global_asm: String::new(), + inline_asm_index: Cell::new(0), cached_context: Context::new(), debug_context, unwind_context, + cgu_name, } } } @@ -205,6 +208,7 @@ &self, ongoing_codegen: Box, _sess: &Session, + _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported> { Ok(*ongoing_codegen .downcast::<(CodegenResults, FxHashMap)>() @@ -268,19 +272,16 @@ let flags = settings::Flags::new(flags_builder); - let variant = cranelift_codegen::isa::BackendVariant::MachInst; - let isa_builder = match sess.opts.cg.target_cpu.as_deref() { Some("native") => { - let builder = cranelift_native::builder_with_options(variant, true).unwrap(); + let builder = cranelift_native::builder_with_options(true).unwrap(); builder } Some(value) => { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) - .unwrap_or_else(|err| { - sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); - }); + cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if let Err(_) = builder.enable(value) { sess.fatal("the specified target cpu isn't currently supported by Cranelift."); } @@ -288,10 +289,9 @@ } None => { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) - .unwrap_or_else(|err| { - sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); - }); + cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if target_triple.architecture == target_lexicon::Architecture::X86_64 { // Don't use "haswell" as the default, as it implies `has_lzcnt`. // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/metadata.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/metadata.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/metadata.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/metadata.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -//! Writing of the rustc metadata for dylibs - -use object::write::{Object, StandardSegment, Symbol, SymbolSection}; -use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope}; - -use rustc_metadata::EncodedMetadata; -use rustc_middle::ty::TyCtxt; - -// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub(crate) fn new_metadata_object( - tcx: TyCtxt<'_>, - cgu_name: &str, - metadata: &EncodedMetadata, -) -> Vec { - use snap::write::FrameEncoder; - use std::io::Write; - - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - - let triple = crate::target_triple(tcx.sess); - - let binary_format = match triple.binary_format { - target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf, - target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff, - target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO, - binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)), - }; - let architecture = match triple.architecture { - target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64, - target_lexicon::Architecture::Arm(_) => object::Architecture::Arm, - target_lexicon::Architecture::Avr => object::Architecture::Avr, - target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon, - target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips, - target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64, - target_lexicon::Architecture::Msp430 => object::Architecture::Msp430, - target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc, - target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64, - target_lexicon::Architecture::Powerpc64le => todo!(), - target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32, - target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64, - target_lexicon::Architecture::S390x => object::Architecture::S390x, - target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64, - target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64, - target_lexicon::Architecture::X86_32(_) => object::Architecture::I386, - target_lexicon::Architecture::X86_64 => object::Architecture::X86_64, - architecture => { - tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,)) - } - }; - let endian = match triple.endianness().unwrap() { - target_lexicon::Endianness::Little => object::Endianness::Little, - target_lexicon::Endianness::Big => object::Endianness::Big, - }; - - let mut object = Object::new(binary_format, architecture, endian); - object.add_file_symbol(cgu_name.as_bytes().to_vec()); - - let segment = object.segment_name(StandardSegment::Data).to_vec(); - let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data); - let offset = object.append_section_data(section_id, &compressed, 1); - // For MachO and probably PE this is necessary to prevent the linker from throwing away the - // .rustc section. For ELF this isn't necessary, but it also doesn't harm. - object.add_symbol(Symbol { - name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(), - value: offset, - size: compressed.len() as u64, - kind: SymbolKind::Data, - scope: SymbolScope::Dynamic, - weak: false, - section: SymbolSection::Section(section_id), - flags: SymbolFlags::None, - }); - - object.write().unwrap() -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs 2022-02-23 04:07:21.000000000 +0000 @@ -57,7 +57,7 @@ use cranelift_codegen::{ entity::SecondaryMap, - ir::{entities::AnyEntity, function::DisplayFunctionAnnotations}, + ir::entities::AnyEntity, write::{FuncWriter, PlainWriter}, }; @@ -129,7 +129,6 @@ &mut self, w: &mut dyn fmt::Write, func: &Function, - reg_info: Option<&isa::RegInfo>, ) -> Result { for comment in &self.global_comments { if !comment.is_empty() { @@ -142,7 +141,7 @@ writeln!(w)?; } - self.super_preamble(w, func, reg_info) + self.super_preamble(w, func) } fn write_entity_definition( @@ -165,11 +164,10 @@ &mut self, w: &mut dyn fmt::Write, func: &Function, - isa: Option<&dyn isa::TargetIsa>, block: Block, indent: usize, ) -> fmt::Result { - PlainWriter.write_block_header(w, func, isa, block, indent) + PlainWriter.write_block_header(w, func, block, indent) } fn write_instruction( @@ -177,11 +175,10 @@ w: &mut dyn fmt::Write, func: &Function, aliases: &SecondaryMap>, - isa: Option<&dyn isa::TargetIsa>, inst: Inst, indent: usize, ) -> fmt::Result { - PlainWriter.write_instruction(w, func, aliases, isa, inst, indent)?; + PlainWriter.write_instruction(w, func, aliases, inst, indent)?; if let Some(comment) = self.entity_comments.get(&inst.into()) { writeln!(w, "; {}", comment.replace('\n', "\n; "))?; } @@ -249,7 +246,6 @@ &mut clif_comments, &mut clif, &context.func, - &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None }, ) .unwrap(); @@ -278,7 +274,6 @@ &mut &self.clif_comments, &mut clif, &self.bcx.func, - &DisplayFunctionAnnotations::default(), ) .unwrap(); writeln!(f, "\n{}", clif) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/trap.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/trap.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/trap.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/trap.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ "puts", Linkage::Import, &Signature { - call_conv: CallConv::triple_default(fx.triple()), + call_conv: fx.target_config.default_call_conv, params: vec![AbiParam::new(fx.pointer_type)], returns: vec![AbiParam::new(types::I32)], }, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs 2022-02-23 04:07:21.000000000 +0000 @@ -329,7 +329,6 @@ // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. size: (u32::try_from(layout.size.bytes()).unwrap() + 15) / 16 * 16, - offset: None, }); CPlace { inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None), layout } } @@ -472,7 +471,6 @@ // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. size: (src_ty.bytes() + 15) / 16 * 16, - offset: None, }); let ptr = Pointer::stack_slot(stack_slot); ptr.store(fx, data, MemFlags::trusted()); @@ -512,6 +510,26 @@ let dst_layout = self.layout(); let to_ptr = match self.inner { CPlaceInner::Var(_local, var) => { + if let ty::Array(element, len) = dst_layout.ty.kind() { + // Can only happen for vector types + let len = + u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); + let vector_ty = fx.clif_type(element).unwrap().by(len).unwrap(); + + let data = match from.0 { + CValueInner::ByRef(ptr, None) => { + let mut flags = MemFlags::new(); + flags.set_notrap(); + ptr.load(fx, vector_ty, flags) + } + CValueInner::ByVal(_) + | CValueInner::ByValPair(_, _) + | CValueInner::ByRef(_, Some(_)) => bug!("array should be ByRef"), + }; + + fx.bcx.def_var(var, data); + return; + } let data = CValue(from.0, dst_layout).load_scalar(fx); let dst_ty = fx.clif_type(self.layout().ty).unwrap(); transmute_value(fx, var, data, dst_ty); @@ -583,7 +601,7 @@ let src_align = src_layout.align.abi.bytes() as u8; let dst_align = dst_layout.align.abi.bytes() as u8; fx.bcx.emit_small_memory_copy( - fx.module.target_config(), + fx.target_config, to_addr, from_addr, size, @@ -605,14 +623,39 @@ let layout = self.layout(); match self.inner { - CPlaceInner::Var(local, var) => { - if let Abi::Vector { .. } = layout.abi { + CPlaceInner::Var(local, var) => match layout.ty.kind() { + ty::Array(_, _) => { + // Can only happen for vector types return CPlace { inner: CPlaceInner::VarLane(local, var, field.as_u32().try_into().unwrap()), layout: layout.field(fx, field.as_u32().try_into().unwrap()), }; } - } + ty::Adt(adt_def, substs) if layout.ty.is_simd() => { + let f0_ty = adt_def.non_enum_variant().fields[0].ty(fx.tcx, substs); + + match f0_ty.kind() { + ty::Array(_, _) => { + assert_eq!(field.as_u32(), 0); + return CPlace { + inner: CPlaceInner::Var(local, var), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + _ => { + return CPlace { + inner: CPlaceInner::VarLane( + local, + var, + field.as_u32().try_into().unwrap(), + ), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + } + } + _ => {} + }, CPlaceInner::VarPair(local, var1, var2) => { let layout = layout.field(&*fx, field.index()); @@ -629,7 +672,12 @@ let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); if field_layout.is_unsized() { - CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) + if let ty::Foreign(_) = field_layout.ty.kind() { + assert!(extra.is_none()); + CPlace::for_ptr(field_ptr, field_layout) + } else { + CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) + } } else { CPlace::for_ptr(field_ptr, field_layout) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json 2022-02-23 04:07:21.000000000 +0000 @@ -5,6 +5,7 @@ "rust-analyzer.assist.importEnforceGranularity": true, "rust-analyzer.assist.importPrefix": "crate", "rust-analyzer.cargo.runBuildScripts": true, + "rust-analyzer.cargo.features": ["unstable-features"] "rust-analyzer.linkedProjects": [ "./Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/y.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/y.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/y.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_cranelift/y.rs 2022-02-23 04:07:21.000000000 +0000 @@ -43,7 +43,9 @@ fn usage() { eprintln!("Usage:"); eprintln!(" ./y.rs prepare"); - eprintln!(" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"); + eprintln!( + " ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -92,6 +94,7 @@ let mut target_dir = PathBuf::from("build"); let mut channel = "release"; let mut sysroot_kind = SysrootKind::Clif; + let mut use_unstable_features = true; while let Some(arg) = args.next().as_deref() { match arg { "--target-dir" => { @@ -109,6 +112,7 @@ None => arg_error!("--sysroot requires argument"), } } + "--no-unstable-features" => use_unstable_features = false, flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag), arg => arg_error!("Unexpected argument {}", arg), } @@ -141,7 +145,8 @@ process::exit(1); } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple); + let cg_clif_build_dir = + build_backend::build_backend(channel, &host_triple, use_unstable_features); build_sysroot::build_sysroot( channel, sysroot_kind, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.lock rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.lock --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.lock 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.lock 2022-02-23 04:07:21.000000000 +0000 @@ -18,12 +18,6 @@ checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1" [[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -36,15 +30,6 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - -[[package]] name = "fm" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -56,7 +41,7 @@ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" dependencies = [ "gccjit_sys", ] @@ -64,7 +49,7 @@ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" dependencies = [ "libc 0.1.12", ] @@ -85,33 +70,17 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", - "libc 0.2.102", + "libc 0.2.112", "wasi", ] [[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.102", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", + "libc 0.2.112", ] [[package]] @@ -122,7 +91,7 @@ dependencies = [ "fm", "getopts", - "libc 0.2.102", + "libc 0.2.112", "num_cpus", "termcolor", "threadpool", @@ -138,9 +107,9 @@ [[package]] name = "libc" -version = "0.2.102" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "memchr" @@ -155,25 +124,14 @@ checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", - "libc 0.2.102", -] - -[[package]] -name = "object" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" -dependencies = [ - "crc32fast", - "indexmap", - "memchr", + "libc 0.2.112", ] [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "rand" @@ -181,7 +139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc 0.2.102", + "libc 0.2.112", "rand_chacha", "rand_core", "rand_hc", @@ -257,7 +215,6 @@ "ar", "gccjit", "lang_tester", - "object", "target-lexicon", "tempfile", ] @@ -284,7 +241,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if", - "libc 0.2.102", + "libc 0.2.112", "rand", "redox_syscall", "remove_dir_all", @@ -321,7 +278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ - "libc 0.2.102", + "libc 0.2.112", ] [[package]] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -23,11 +23,6 @@ ar = "0.8.0" -[dependencies.object] -version = "0.25.0" -default-features = false -features = ["read", "std", "write"] # We don't need WASM support. - [dev-dependencies] lang_tester = "0.3.9" tempfile = "3.1.0" diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/config.sh rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/config.sh --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/config.sh 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/config.sh 2022-02-23 04:07:21.000000000 +0000 @@ -38,7 +38,7 @@ fi fi -export RUSTFLAGS="$linker -Cpanic=abort -Zsymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" +export RUSTFLAGS="$linker -Cpanic=abort -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" # FIXME(antoyo): remove once the atomic shim is gone if [[ `uname` == 'Darwin' ]]; then diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch 2022-02-23 04:07:21.000000000 +0000 @@ -46,4 +46,24 @@ #[test] fn cell_allows_array_cycle() { +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 3e00e0a..8e5663b 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2108,6 +2108,7 @@ fn test_copy_within_panics_src_out_of_bounds() { + bytes.copy_within(usize::MAX..=usize::MAX, 0); + } + ++/* + #[test] + fn test_is_sorted() { + let empty: [i32; 0] = []; +@@ -2122,6 +2123,7 @@ fn test_is_sorted() { + assert!(!["c", "bb", "aaa"].is_sorted()); + assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len())); + } ++*/ + + #[test] + fn test_slice_run_destructors() { -- 2.21.0 (Apple Git-122) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,24 @@ +From b1ae000f6da1abd3b8e9b80c40bc11c89b8ae93c Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Thu, 30 Dec 2021 16:54:40 +0100 +Subject: [PATCH] [core] Disable portable-simd test + +--- + library/core/tests/lib.rs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs +index ec70034..7cd9e21 100644 +--- a/library/core/tests/lib.rs ++++ b/library/core/tests/lib.rs +@@ -121,7 +121,6 @@ mod pattern; + mod pin; + mod ptr; + mod result; +-mod simd; + mod slice; + mod str; + mod str_lossy; +-- +2.26.2.7.g19db9cfb68 + diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,30 @@ +From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Fri, 3 Dec 2021 12:16:30 +0100 +Subject: [PATCH] Disable long running tests + +--- + library/core/tests/slice.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 2c8f00a..44847ee 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut { + }; + } + ++/* + #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) + take_tests! { + slice: &[(); usize::MAX], method: take, + (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), +@@ -2345,3 +2347,4 @@ take_tests! { + (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), + } ++*/ +-- +2.26.2.7.g19db9cfb68 + diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Readme.md rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Readme.md --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Readme.md 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/Readme.md 2022-02-23 04:07:21.000000000 +0000 @@ -111,6 +111,8 @@ p loc->m_line ``` +To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`. + ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/rust-toolchain rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/rust-toolchain --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/rust-toolchain 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/rust-toolchain 2022-02-23 04:07:21.000000000 +0000 @@ -1 +1 @@ -nightly-2021-09-28 +nightly-2021-12-30 diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/abi.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/abi.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/abi.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/abi.rs 2022-02-23 04:07:21.000000000 +0000 @@ -48,8 +48,8 @@ let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.gcc_type(cx)) + .flat_map(|option_reg| { + option_reg.map(|reg| reg.gcc_type(cx)) }) .chain((0..rest_count).map(|_| rest_gcc_unit)) .collect(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,30 +18,30 @@ // Rust asm! and GCC Extended Asm semantics differ substantially. // -// 1. Rust asm operands go along as one list of operands. Operands themselves indicate -// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be +// 1. Rust asm operands go along as one list of operands. Operands themselves indicate +// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be // both "in" and "out" (`inout(reg)`). // -// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit, -// this means that all "out" operands must go before "in" operands. "In" and "out" operands +// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit, +// this means that all "out" operands must go before "in" operands. "In" and "out" operands // cannot interleave. // -// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important +// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important // because the asm template refers to operands by index. // // Mapping from Rust to GCC index would be 1-1 if it wasn't for... // -// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. -// Contrary, Rust expresses clobbers through "out" operands that aren't tied to +// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. +// Contrary, Rust expresses clobbers through "out" operands that aren't tied to // a variable (`_`), and such "clobbers" do have index. // -// 4. Furthermore, GCC Extended Asm does not support explicit register constraints -// (like `out("eax")`) directly, offering so-called "local register variables" -// as a workaround. These variables need to be declared and initialized *before* -// the Extended Asm block but *after* normal local variables +// 4. Furthermore, GCC Extended Asm does not support explicit register constraints +// (like `out("eax")`) directly, offering so-called "local register variables" +// as a workaround. These variables need to be declared and initialized *before* +// the Extended Asm block but *after* normal local variables // (see comment in `codegen_inline_asm` for explanation). // -// With that in mind, let's see how we translate Rust syntax to GCC +// With that in mind, let's see how we translate Rust syntax to GCC // (from now on, `CC` stands for "constraint code"): // // * `out(reg_class) var` -> translated to output operand: `"=CC"(var)` @@ -52,18 +52,17 @@ // // * `out("explicit register") _` -> not translated to any operands, register is simply added to clobbers list // -// * `inout(reg_class) in_var => out_var` -> translated to two operands: +// * `inout(reg_class) in_var => out_var` -> translated to two operands: // output: `"=CC"(in_var)` -// input: `"num"(out_var)` where num is the GCC index +// input: `"num"(out_var)` where num is the GCC index // of the corresponding output operand // -// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`, +// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`, // where "tmp" is a temporary unused variable // -// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above -// with `"r"(var)` constraint, +// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above +// with `"r"(var)` constraint, // and one register variable assigned to the desired register. -// const ATT_SYNTAX_INS: &str = ".att_syntax noprefix\n\t"; const INTEL_SYNTAX_INS: &str = "\n\t.intel_syntax noprefix"; @@ -118,13 +117,20 @@ true } - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + if options.contains(InlineAsmOptions::MAY_UNWIND) { + self.sess() + .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm") + .emit(); + return; + } + let asm_arch = self.tcx.sess.asm_arch.unwrap(); let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX); let intel_dialect = is_x86 && !options.contains(InlineAsmOptions::ATT_SYNTAX); - // GCC index of an output operand equals its position in the array + // GCC index of an output operand equals its position in the array let mut outputs = vec![]; // GCC index of an input operand equals its position in the array @@ -138,9 +144,9 @@ let mut constants_len = 0; // There are rules we must adhere to if we want GCC to do the right thing: - // + // // * Every local variable that the asm block uses as an output must be declared *before* - // the asm block. + // the asm block. // * There must be no instructions whatsoever between the register variables and the asm. // // Therefore, the backend must generate the instructions strictly in this order: @@ -152,7 +158,7 @@ // We also must make sure that no input operands are emitted before output operands. // // This is why we work in passes, first emitting local vars, then local register vars. - // Also, we don't emit any asm operands immediately; we save them to + // Also, we don't emit any asm operands immediately; we save them to // the one of the buffers to be emitted later. // 1. Normal variables (and saving operands to buffers). @@ -165,7 +171,7 @@ (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx, false)), // When `reg` is a class and not an explicit register but the out place is not specified, // we need to create an unused output variable to assign the output to. This var - // needs to be of a type that's "compatible" with the register class, but specific type + // needs to be of a type that's "compatible" with the register class, but specific type // doesn't matter. (Constraint(constraint), None) => (constraint, dummy_output_type(self.cx, reg.reg_class())), (Register(_), Some(_)) => { @@ -193,7 +199,7 @@ let tmp_var = self.current_func().new_local(None, ty, "output_register"); outputs.push(AsmOutOperand { - constraint, + constraint, rust_idx, late, readwrite: false, @@ -204,12 +210,12 @@ InlineAsmOperandRef::In { reg, value } => { if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { - inputs.push(AsmInOperand { - constraint: Cow::Borrowed(constraint), - rust_idx, + inputs.push(AsmInOperand { + constraint: Cow::Borrowed(constraint), + rust_idx, val: value.immediate() }); - } + } else { // left for the next pass continue @@ -219,7 +225,7 @@ InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { constraint - } + } else { // left for the next pass continue @@ -228,22 +234,22 @@ // Rustc frontend guarantees that input and output types are "compatible", // so we can just use input var's type for the output variable. // - // This decision is also backed by the fact that LLVM needs in and out - // values to be of *exactly the same type*, not just "compatible". + // This decision is also backed by the fact that LLVM needs in and out + // values to be of *exactly the same type*, not just "compatible". // I'm not sure if GCC is so picky too, but better safe than sorry. let ty = in_value.layout.gcc_type(self.cx, false); let tmp_var = self.current_func().new_local(None, ty, "output_register"); // If the out_place is None (i.e `inout(reg) _` syntax was used), we translate - // it to one "readwrite (+) output variable", otherwise we translate it to two + // it to one "readwrite (+) output variable", otherwise we translate it to two // "out and tied in" vars as described above. let readwrite = out_place.is_none(); outputs.push(AsmOutOperand { - constraint, + constraint, rust_idx, late, readwrite, - tmp_var, + tmp_var, out_place, }); @@ -252,8 +258,8 @@ let constraint = Cow::Owned(out_gcc_idx.to_string()); inputs.push(AsmInOperand { - constraint, - rust_idx, + constraint, + rust_idx, val: in_value.immediate() }); } @@ -280,7 +286,7 @@ if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { let out_place = if let Some(place) = place { place - } + } else { // processed in the previous pass continue @@ -291,7 +297,7 @@ tmp_var.set_register_name(reg_name); outputs.push(AsmOutOperand { - constraint: "r".into(), + constraint: "r".into(), rust_idx, late, readwrite: false, @@ -311,9 +317,9 @@ reg_var.set_register_name(reg_name); self.llbb().add_assignment(None, reg_var, value.immediate()); - inputs.push(AsmInOperand { - constraint: "r".into(), - rust_idx, + inputs.push(AsmInOperand { + constraint: "r".into(), + rust_idx, val: reg_var.to_rvalue() }); } @@ -324,31 +330,23 @@ // `inout("explicit register") in_var => out_var` InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { - let out_place = if let Some(place) = out_place { - place - } - else { - // processed in the previous pass - continue - }; - // See explanation in the first pass. let ty = in_value.layout.gcc_type(self.cx, false); let tmp_var = self.current_func().new_local(None, ty, "output_register"); tmp_var.set_register_name(reg_name); outputs.push(AsmOutOperand { - constraint: "r".into(), + constraint: "r".into(), rust_idx, late, readwrite: false, tmp_var, - out_place: Some(out_place) + out_place, }); let constraint = Cow::Owned((outputs.len() - 1).to_string()); - inputs.push(AsmInOperand { - constraint, + inputs.push(AsmInOperand { + constraint, rust_idx, val: in_value.immediate() }); @@ -357,8 +355,8 @@ // processed in the previous pass } - InlineAsmOperandRef::Const { .. } - | InlineAsmOperandRef::SymFn { .. } + InlineAsmOperandRef::Const { .. } + | InlineAsmOperandRef::SymFn { .. } | InlineAsmOperandRef::SymStatic { .. } => { // processed in the previous pass } @@ -453,7 +451,7 @@ if !intel_dialect { template_str.push_str(INTEL_SYNTAX_INS); } - + // 4. Generate Extended Asm block let block = self.llbb(); @@ -472,7 +470,7 @@ } if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { - // TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient + // TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient // on all architectures. For instance, what about FP stack? extended_asm.add_clobber("cc"); } @@ -491,10 +489,10 @@ self.call(self.type_void(), builtin_unreachable, &[], None); } - // Write results to outputs. + // Write results to outputs. // // We need to do this because: - // 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases + // 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases // (especially with current `rustc_backend_ssa` API). // 2. Not every output operand has an `out_place`, and it's required by `add_output_operand`. // @@ -502,7 +500,7 @@ // generates `out_place = tmp_var;` assignments if out_place exists. for op in &outputs { if let Some(place) = op.out_place { - OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); + OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); } } @@ -561,7 +559,6 @@ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(), @@ -570,6 +567,7 @@ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(), + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(), @@ -620,8 +618,7 @@ | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)=> cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -632,6 +629,7 @@ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { unimplemented!() } + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), @@ -728,8 +726,7 @@ | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -740,6 +737,7 @@ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { unimplemented!() } + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(_) => unimplemented!(), InlineAsmRegClass::Mips(_) => unimplemented!(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/back/write.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/back/write.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/back/write.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/back/write.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,4 @@ -use std::fs; +use std::{env, fs}; use gccjit::OutputKind; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; @@ -32,7 +32,7 @@ if config.emit_asm { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -41,18 +41,18 @@ EmitObj::ObjectCode(_) => { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); - match &*module.name { - "std_example.7rcbfp3g-cgu.15" => { - println!("Dumping reproducer {}", module.name); - let _ = fs::create_dir("/tmp/reproducers"); - // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by - // transmuting an rvalue to an lvalue. - // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue - context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); - println!("Dumped reproducer {}", module.name); - }, - _ => (), + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); + if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") { + println!("Module {}", module.name); + } + if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) { + println!("Dumping reproducer {}", module.name); + let _ = fs::create_dir("/tmp/reproducers"); + // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by + // transmuting an rvalue to an lvalue. + // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue + context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); + println!("Dumped reproducer {}", module.name); } context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/base.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,14 +7,12 @@ GlobalKind, }; use rustc_middle::dep_graph; -use rustc_middle::middle::exported_symbols; use rustc_middle::ty::TyCtxt; use rustc_middle::mir::mono::Linkage; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoMethods; -use rustc_metadata::EncodedMetadata; use rustc_session::config::DebugInfo; use rustc_span::Symbol; @@ -83,7 +81,10 @@ for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { context.set_dump_code_on_compile(true); } @@ -132,40 +133,3 @@ (module, cost) } - -pub fn write_compressed_metadata<'tcx>(tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut GccContext) { - use snap::write::FrameEncoder; - use std::io::Write; - - // Historical note: - // - // When using link.exe it was seen that the section name `.note.rustc` - // was getting shortened to `.note.ru`, and according to the PE and COFF - // specification: - // - // > Executable images do not use a string table and do not support - // > section names longer than 8 characters - // - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - // - // As a result, we choose a slightly shorter name! As to why - // `.note.rustc` works on MinGW, see - // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 - let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" }; - - let context = &gcc_module.context; - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data()).unwrap(); - - let name = exported_symbols::metadata_symbol_name(tcx); - let typ = context.new_array_type(None, context.new_type::(), compressed.len() as i32); - let global = context.new_global(None, GlobalKind::Exported, typ, name); - global.global_set_initializer(&compressed); - global.set_link_section(section_name); - - // Also generate a .section directive to force no - // flags, at least for ELF outputs, so that the - // metadata doesn't get loaded into memory. - let directive = format!(".section {}", section_name); - context.add_top_level_asm(None, &directive); -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/builder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/builder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/builder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/builder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -200,7 +200,7 @@ fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { let mut all_args_match = true; let mut param_types = vec![]; - let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) { let param = gcc_func.get_param_type(index); if param != arg.get_type() { @@ -277,7 +277,7 @@ // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). - let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); let mut return_type = gcc_func.get_return_type(); let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); @@ -605,22 +605,17 @@ } fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: - // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 if a.get_type() != b.get_type() { b = self.context.new_cast(None, b, a.get_type()); } - let res = self.current_func().new_local(None, b.get_type(), "andResult"); - self.llbb().add_assignment(None, res, a & b); - res.to_rvalue() + a & b } - fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: - // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 - let res = self.current_func().new_local(None, b.get_type(), "orResult"); - self.llbb().add_assignment(None, res, a | b); - res.to_rvalue() + fn or(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + if a.get_type() != b.get_type() { + b = self.context.new_cast(None, b, a.get_type()); + } + a | b } fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -628,8 +623,7 @@ } fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): use new_unary_op()? - self.cx.context.new_rvalue_from_long(a.get_type(), 0) - a + self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) } fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -816,7 +810,10 @@ let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes())); let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); - let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let volatile_const_void_ptr_type = self.context.new_type::<()>() + .make_const() + .make_volatile() + .make_pointer(); let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); self.context.new_call(None, atomic_load, &[ptr, ordering]) } @@ -941,7 +938,9 @@ // TODO(antoyo): handle alignment. let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes())); let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); - let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let volatile_const_void_ptr_type = self.context.new_type::<()>() + .make_volatile() + .make_pointer(); let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because @@ -981,12 +980,12 @@ assert_eq!(idx as usize as u64, idx); let value = ptr.dereference(None).to_rvalue(); - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, value, index); element.get_address(None) } - else if let Some(vector_type) = value_type.is_vector() { + else if let Some(vector_type) = value_type.dyncast_vector() { let array_type = vector_type.get_element_type().make_pointer(); let array = self.bitcast(ptr, array_type); let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); @@ -1009,7 +1008,7 @@ fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): check that it indeed sign extend the value. - if dest_ty.is_vector().is_some() { + if dest_ty.dyncast_vector().is_some() { // TODO(antoyo): nothing to do as it is only for LLVM? return value; } @@ -1081,7 +1080,7 @@ let right_type = rhs.get_type(); if left_type != right_type { // NOTE: because libgccjit cannot compare function pointers. - if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() { + if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() { lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); } @@ -1189,12 +1188,12 @@ assert_eq!(idx as usize as u64, idx); let value_type = aggregate_value.get_type(); - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, aggregate_value, index); element.get_address(None) } - else if value_type.is_vector().is_some() { + else if value_type.dyncast_vector().is_some() { panic!(); } else if let Some(pointer_type) = value_type.get_pointee() { @@ -1221,11 +1220,11 @@ let value_type = aggregate_value.get_type(); let lvalue = - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); self.context.new_array_access(None, aggregate_value, index) } - else if value_type.is_vector().is_some() { + else if value_type.dyncast_vector().is_some() { panic!(); } else if let Some(pointer_type) = value_type.get_pointee() { @@ -1404,7 +1403,7 @@ self.cx } - fn do_not_inline(&mut self, _llret: RValue<'gcc>) { + fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) { unimplemented!(); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/common.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/common.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/common.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/common.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,4 @@ use std::convert::TryFrom; -use std::convert::TryInto; use gccjit::LValue; use gccjit::{Block, CType, RValue, Type, ToRValue}; @@ -33,7 +32,7 @@ return value; } - let global = self.global_string(&*symbol.as_str()); + let global = self.global_string(symbol.as_str()); self.const_cstr_cache.borrow_mut().insert(symbol, global); global @@ -44,7 +43,7 @@ let string = self.context.new_string_literal(&*string); let sym = self.generate_local_symbol_name("str"); let global = self.declare_private_global(&sym, self.val_ty(string)); - global.global_set_initializer_value(string); + global.global_set_initializer_rvalue(string); global // TODO(antoyo): set linkage. } @@ -79,7 +78,7 @@ bytes.iter() .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) .collect(); - context.new_rvalue_from_array(None, typ, &elements) + context.new_array_constructor(None, typ, &elements) } pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool { @@ -120,13 +119,6 @@ } fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> { - let num64: Result = num.try_into(); - if let Ok(num) = num64 { - // FIXME(antoyo): workaround for a bug where libgccjit is expecting a constant. - // The operations >> 64 and | low are making the normal case a non-constant. - return self.context.new_rvalue_from_long(typ, num as i64); - } - if num >> 64 != 0 { // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()? let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); @@ -193,7 +185,7 @@ // TODO(antoyo): cache the type? It's anonymous, so probably not. let typ = self.type_struct(&fields, packed); let struct_type = typ.is_struct().expect("struct type"); - self.context.new_rvalue_from_struct(None, struct_type, values) + self.context.new_struct_constructor(None, struct_type.as_type(), None, values) } fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/consts.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/consts.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/consts.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/consts.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,7 +20,7 @@ pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { if value.get_type() == self.bool_type.make_pointer() { if let Some(pointee) = typ.get_pointee() { - if pointee.is_vector().is_some() { + if pointee.dyncast_vector().is_some() { panic!() } } @@ -31,9 +31,13 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> { - if let Some(global_value) = self.const_globals.borrow().get(&cv) { - // TODO(antoyo): upgrade alignment. - return *global_value; + // TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the + // following: + for (value, variable) in &*self.const_globals.borrow() { + if format!("{:?}", value) == format!("{:?}", cv) { + // TODO(antoyo): upgrade alignment. + return *variable; + } } let global_value = self.static_addr_of_mut(cv, align, kind); // TODO(antoyo): set global constant. @@ -77,7 +81,7 @@ else { value }; - global.global_set_initializer_value(value); + global.global_set_initializer_rvalue(value); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -176,7 +180,7 @@ }; // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used // globally. - global.global_set_initializer_value(cv); + global.global_set_initializer_rvalue(cv); // TODO(antoyo): set unnamed address. global.get_address(None) } @@ -371,7 +375,7 @@ real_name.push_str(&sym); let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section); // TODO(antoyo): set linkage. - global2.global_set_initializer_value(global1.get_address(None)); + global2.global_set_initializer_rvalue(global1.get_address(None)); // TODO(antoyo): use global_set_initializer() when it will work. global2 } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/context.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/context.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/context.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/context.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,16 +1,6 @@ use std::cell::{Cell, RefCell}; -use gccjit::{ - Block, - Context, - CType, - Function, - FunctionType, - LValue, - RValue, - Struct, - Type, -}; +use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::traits::{ BackendTypes, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/declare.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/declare.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/declare.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/declare.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,7 +17,7 @@ global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - global.set_link_section(&link_section.as_str()); + global.set_link_section(link_section.as_str()); } global } @@ -53,7 +53,7 @@ global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - global.set_link_section(&link_section.as_str()); + global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); self.globals.borrow_mut().insert(name.to_string(), global_address); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -88,7 +88,7 @@ let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); - let name_str = &*name.as_str(); + let name_str = name.as_str(); let llret_ty = self.layout_of(ret_ty).gcc_type(self, true); let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); @@ -526,7 +526,7 @@ let value = if result_type.is_signed(self.cx) { - self.context.new_bitcast(None, value, typ) + self.context.new_cast(None, value, typ) } else { value @@ -690,7 +690,7 @@ }, }; - self.context.new_bitcast(None, result, result_type) + self.context.new_cast(None, result, result_type) } fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { @@ -741,6 +741,11 @@ let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); let not_low_and_not_high = not_low & not_high; let index = not_high + not_low_and_not_high; + // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in + // gcc. + // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the + // compilation stage. + let index = self.context.new_cast(None, index, self.i32_type); let res = self.context.new_array_access(None, result, index); @@ -764,7 +769,7 @@ let arg = if result_type.is_signed(self.cx) { let new_type = result_type.to_unsigned(self.cx); - self.context.new_bitcast(None, arg, new_type) + self.context.new_cast(None, arg, new_type) } else { arg @@ -816,10 +821,15 @@ let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); let not_low_and_not_high = not_low & not_high; let index = not_low + not_low_and_not_high; + // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in + // gcc. + // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the + // compilation stage. + let index = self.context.new_cast(None, index, self.i32_type); let res = self.context.new_array_access(None, result, index); - return self.context.new_bitcast(None, res, result_type); + return self.context.new_cast(None, res, result_type); } else { unimplemented!("count_trailing_zeroes for {:?}", arg_type); @@ -833,7 +843,7 @@ arg }; let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); - self.context.new_bitcast(None, res, result_type) + self.context.new_cast(None, res, result_type) } fn int_width(&self, typ: Type<'gcc>) -> i64 { @@ -847,7 +857,7 @@ let value = if result_type.is_signed(self.cx) { - self.context.new_bitcast(None, value, value_type) + self.context.new_cast(None, value, value_type) } else { value @@ -863,7 +873,7 @@ let low = self.context.new_cast(None, value, self.cx.ulonglong_type); let low = self.context.new_call(None, popcount, &[low]); let res = high + low; - return self.context.new_bitcast(None, res, result_type); + return self.context.new_cast(None, res, result_type); } // First step. @@ -888,7 +898,7 @@ let value = left + right; if value_type.is_u8(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Fourth step. @@ -899,7 +909,7 @@ let value = left + right; if value_type.is_u16(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Fifth step. @@ -910,7 +920,7 @@ let value = left + right; if value_type.is_u32(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Sixth step. @@ -920,7 +930,7 @@ let right = shifted & mask; let value = left + right; - self.context.new_bitcast(None, value, result_type) + self.context.new_cast(None, value, result_type) } // Algorithm from: https://blog.regehr.org/archives/1063 diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs 2022-02-23 04:07:21.000000000 +0000 @@ -52,7 +52,7 @@ let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); - let name_str = &*name.as_str(); + let name_str = name.as_str(); // every intrinsic below takes a SIMD vector as its first argument require_simd!(arg_tys[0], "input"); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,9 +20,7 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; -extern crate rustc_symbol_mangling; extern crate rustc_target; -extern crate snap; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] @@ -92,12 +90,10 @@ let target_cpu = target_cpu(tcx.sess); let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module); - rustc_symbol_mangling::test::report_symbol_names(tcx); - Box::new(res) } - fn join_codegen(&self, ongoing_codegen: Box, sess: &Session) -> Result<(CodegenResults, FxHashMap), ErrorReported> { + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxHashMap), ErrorReported> { let (codegen_results, work_products) = ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") @@ -128,10 +124,6 @@ } } - fn write_compressed_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut Self::Module) { - base::write_compressed_metadata(tcx, metadata, gcc_module) - } - fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, mods: &mut Self::Module, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { unsafe { allocator::codegen(tcx, mods, module_name, kind, has_alloc_error_handler) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/type_.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/type_.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/type_.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/src/type_.rs 2022-02-23 04:07:21.000000000 +0000 @@ -122,7 +122,7 @@ if typ.is_integral() { TypeKind::Integer } - else if typ.is_vector().is_some() { + else if typ.dyncast_vector().is_some() { TypeKind::Vector } else { @@ -141,10 +141,10 @@ } fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> { - if let Some(typ) = ty.is_array() { + if let Some(typ) = ty.dyncast_array() { typ } - else if let Some(vector_type) = ty.is_vector() { + else if let Some(vector_type) = ty.dyncast_vector() { vector_type.get_element_type() } else if let Some(typ) = ty.get_pointee() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/tests/run/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/tests/run/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/tests/run/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/tests/run/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,9 @@ // Run-time: // status: 0 -#![feature(asm, global_asm)] +#![feature(asm_const, asm_sym)] + +use std::arch::{asm, global_asm}; global_asm!(" .global add_asm @@ -17,6 +19,16 @@ fn add_asm(a: i64, b: i64) -> i64; } +pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { + asm!( + "rep movsb", + inout("rdi") dst => _, + inout("rsi") src => _, + inout("rcx") len => _, + options(preserves_flags, nostack) + ); +} + fn main() { unsafe { asm!("nop"); @@ -62,11 +74,11 @@ } assert_eq!(x, 43); - // check inout(reg_class) x + // check inout(reg_class) x let mut x: u64 = 42; unsafe { asm!("add {0}, {0}", - inout(reg) x + inout(reg) x ); } assert_eq!(x, 84); @@ -75,7 +87,7 @@ let mut x: u64 = 42; unsafe { asm!("add r11, r11", - inout("r11") x + inout("r11") x ); } assert_eq!(x, 84); @@ -98,12 +110,12 @@ assert_eq!(res, 7); assert_eq!(rem, 2); - // check const + // check const let mut x: u64 = 42; unsafe { asm!("add {}, {}", inout(reg) x, - const 1 + const 1 ); } assert_eq!(x, 43); @@ -150,4 +162,11 @@ assert_eq!(x, 42); assert_eq!(unsafe { add_asm(40, 2) }, 42); + + let array1 = [1u8, 2, 3]; + let mut array2 = [0u8, 0, 0]; + unsafe { + mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3); + } + assert_eq!(array1, array2); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/test.sh rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/test.sh --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/test.sh 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_gcc/test.sh 2022-02-23 04:07:21.000000000 +0000 @@ -183,7 +183,7 @@ git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro. - RUSTC_ARGS="-Zpanic-abort-tests -Zsymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" + RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" echo "[TEST] rustc test suite" COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/ui/ --rustc-args "$RUSTC_ARGS" diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -11,8 +11,8 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" +libloading = "0.7.1" measureme = "10.0.0" -snap = "1" tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/abi.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/abi.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/abi.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/abi.rs 2022-02-23 04:07:21.000000000 +0000 @@ -136,11 +136,11 @@ } pub trait LlvmType { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } impl LlvmType for Reg { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { match self.kind { RegKind::Integer => cx.type_ix(self.size.bits()), RegKind::Float => match self.size.bits() { @@ -154,7 +154,7 @@ } impl LlvmType for CastTarget { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 { (0, 0) @@ -181,9 +181,7 @@ let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx)) - }) + .flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); @@ -214,7 +212,7 @@ ); } -impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { +impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { /// Gets the LLVM type for a place of the original Rust type of /// this argument/return, i.e., the result of `type_of::type_of`. fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { @@ -289,7 +287,7 @@ fn store_fn_arg( &self, - bx: &mut Builder<'a, 'll, 'tcx>, + bx: &mut Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, &'ll Value>, ) { @@ -316,7 +314,7 @@ } } -impl ArgAbiMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> ArgAbiMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn store_fn_arg( &mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, @@ -338,15 +336,15 @@ } } -pub trait FnAbiLlvmExt<'tcx> { +pub trait FnAbiLlvmExt<'ll, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value); - fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value); + fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value); } -impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { +impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { // Ignore "extra" args from the call site for C variadic functions. // Only the "fixed" args are part of the LLVM function signature. @@ -466,6 +464,9 @@ ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); + } _ => {} } for arg in &self.args { @@ -497,14 +498,14 @@ apply(a); apply(b); } - PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(&cast.attrs); } } } } - fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { + fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) { if self.ret.layout.abi.is_uninhabited() { llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite); } @@ -533,6 +534,13 @@ ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_callsite( + llvm::AttributePlace::ReturnValue, + &bx.cx, + callsite, + ); + } _ => {} } if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { @@ -577,8 +585,8 @@ apply(bx.cx, a); apply(bx.cx, b); } - PassMode::Cast(_) => { - apply(bx.cx, &ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(bx.cx, &cast.attrs); } } } @@ -602,7 +610,7 @@ } } -impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value) { fn_abi.apply_attrs_callsite(self, callsite) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,8 @@ use crate::builder::Builder; +use crate::common::Funclet; use crate::context::CodegenCx; use crate::llvm; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -21,7 +23,7 @@ use libc::{c_char, c_uint}; use tracing::debug; -impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn codegen_llvm_inline_asm( &mut self, ia: &hir::LlvmInlineAsmInner, @@ -98,6 +100,8 @@ ia.alignstack, ia.dialect, &[span], + false, + None, ); if r.is_none() { return false; @@ -121,6 +125,7 @@ options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, + dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -314,6 +319,9 @@ "~{vxrm}".to_string(), ]); } + InlineAsmArch::Avr => { + constraints.push("~{sreg}".to_string()); + } InlineAsmArch::Nvptx64 => {} InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} @@ -355,6 +363,8 @@ alignstack, dialect, line_spans, + options.contains(InlineAsmOptions::MAY_UNWIND), + dest_catch_funclet, ) .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed")); @@ -389,7 +399,7 @@ } } -impl AsmMethods for CodegenCx<'ll, 'tcx> { +impl AsmMethods for CodegenCx<'_, '_> { fn codegen_global_asm( &self, template: &[InlineAsmTemplatePiece], @@ -437,8 +447,8 @@ } } -pub(crate) fn inline_asm_call( - bx: &mut Builder<'a, 'll, 'tcx>, +pub(crate) fn inline_asm_call<'ll>( + bx: &mut Builder<'_, 'll, '_>, asm: &str, cons: &str, inputs: &[&'ll Value], @@ -447,9 +457,16 @@ alignstack: bool, dia: LlvmAsmDialect, line_spans: &[Span], + unwind: bool, + dest_catch_funclet: Option<( + &'ll llvm::BasicBlock, + &'ll llvm::BasicBlock, + Option<&Funclet<'ll>>, + )>, ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; let alignstack = if alignstack { llvm::True } else { llvm::False }; + let can_throw = if unwind { llvm::True } else { llvm::False }; let argtys = inputs .iter() @@ -460,12 +477,19 @@ .collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = bx.cx.type_func(&argtys[..], output); + let fty = bx.cx.type_func(&argtys, output); unsafe { // Ask LLVM to verify that the constraints are well-formed. let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len()); debug!("constraint verification result: {:?}", constraints_ok); if constraints_ok { + if unwind && llvm_util::get_version() < (13, 0, 0) { + bx.cx.sess().span_fatal( + line_spans[0], + "unwinding from inline assembly is only supported on llvm >= 13.", + ); + } + let v = llvm::LLVMRustInlineAsm( fty, asm.as_ptr().cast(), @@ -475,8 +499,14 @@ volatile, alignstack, llvm::AsmDialect::from_generic(dia), + can_throw, ); - let call = bx.call(fty, v, inputs, None); + + let call = if let Some((dest, catch, funclet)) = dest_catch_funclet { + bx.invoke(fty, v, inputs, dest, catch, funclet) + } else { + bx.call(fty, v, inputs, None) + }; // Store mark in a metadata node so we can map LLVM errors // back to source locations. See #17552. @@ -553,7 +583,7 @@ } /// Converts a register class to an LLVM constraint code. -fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) -> String { +fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> String { match reg { // For vector registers LLVM wants the register name to match the type size. InlineAsmRegOrRegClass::Reg(reg) => { @@ -602,7 +632,6 @@ unreachable!("clobber-only") } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => "t", @@ -642,6 +671,11 @@ InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { @@ -668,8 +702,7 @@ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None, + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -722,6 +755,14 @@ } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Bpf(_) => None, + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) + | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) + | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier { + Some('h') => Some('B'), + Some('l') => Some('A'), + _ => None, + }, + InlineAsmRegClass::Avr(_) => None, InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") @@ -732,7 +773,7 @@ /// Type to use for outputs that are discarded. It doesn't really matter what /// the type is, as long as it is valid for the constraint code. -fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll Type { +fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'ll Type { match reg { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) @@ -742,8 +783,7 @@ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -785,6 +825,11 @@ InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { @@ -796,7 +841,7 @@ /// Helper function to get the LLVM type for a Scalar. Pointers are returned as /// the equivalent integer type. -fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type { +fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type { match scalar.value { Primitive::Int(Integer::I8, _) => cx.type_i8(), Primitive::Int(Integer::I16, _) => cx.type_i16(), @@ -810,8 +855,8 @@ } /// Fix up an input value to work around LLVM bugs. -fn llvm_fixup_input( - bx: &mut Builder<'a, 'll, 'tcx>, +fn llvm_fixup_input<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, @@ -888,8 +933,8 @@ } /// Fix up an output value to work around LLVM bugs. -fn llvm_fixup_output( - bx: &mut Builder<'a, 'll, 'tcx>, +fn llvm_fixup_output<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, @@ -964,7 +1009,7 @@ } /// Output type to use for llvm_fixup_output. -fn llvm_fixup_output_type( +fn llvm_fixup_output_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/attributes.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/attributes.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/attributes.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/attributes.rs 2022-02-23 04:07:21.000000000 +0000 @@ -25,7 +25,7 @@ /// Mark LLVM function to use provided inline heuristic. #[inline] -fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { +fn inline<'ll>(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), @@ -41,7 +41,7 @@ /// Apply LLVM sanitize attributes. #[inline] -pub fn sanitize(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll Value) { +pub fn sanitize<'ll>(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll Value) { let enabled = cx.tcx.sess.opts.debugging_opts.sanitizer - no_sanitize; if enabled.contains(SanitizerSet::ADDRESS) { llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn); @@ -59,17 +59,17 @@ /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn emit_uwtable(val: &'ll Value, emit: bool) { +pub fn emit_uwtable(val: &Value, emit: bool) { Attribute::UWTable.toggle_llfn(Function, val, emit); } /// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue. #[inline] -fn naked(val: &'ll Value, is_naked: bool) { +fn naked(val: &Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn set_frame_pointer_type<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let mut fp = cx.sess().target.frame_pointer; // "mcount" function relies on stack pointer. // See . @@ -92,7 +92,7 @@ /// Tell LLVM what instrument function to insert. #[inline] -fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_instrument_function<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().instrument_mcount() { // Similar to `clang -pg` behavior. Handled by the // `post-inline-ee-instrument` LLVM pass. @@ -110,7 +110,7 @@ } } -fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_probestack<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Currently stack probes seem somewhat incompatible with the address // sanitizer and thread sanitizer. With asan we're already protected from // stack overflow anyway so we don't really need stack probes regardless. @@ -161,7 +161,7 @@ } } -fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_stackprotector<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let sspattr = match cx.sess().stack_protector() { StackProtector::None => return, StackProtector::All => Attribute::StackProtectReq, @@ -172,7 +172,7 @@ sspattr.apply_llfn(Function, llfn) } -pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn apply_target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( llfn, @@ -182,7 +182,7 @@ ); } -pub fn apply_tune_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn apply_tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if let Some(tune) = llvm_util::tune_cpu(cx.tcx.sess) { let tune_cpu = SmallCStr::new(tune); llvm::AddFunctionAttrStringValue( @@ -196,14 +196,14 @@ /// Sets the `NonLazyBind` LLVM attribute on a given function, /// assuming the codegen options allow skipping the PLT. -pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) { +pub fn non_lazy_bind<'ll>(sess: &Session, llfn: &'ll Value) { // Don't generate calls through PLT if it's not necessary if !sess.needs_plt() { Attribute::NonLazyBind.apply_llfn(Function, llfn); } } -pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) { +pub(crate) fn default_optimisation_attrs<'ll>(sess: &Session, llfn: &'ll Value) { match sess.opts.optimize { OptLevel::Size => { llvm::Attribute::MinSize.unapply_llfn(Function, llfn); @@ -226,7 +226,11 @@ /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. -pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>) { +pub fn from_fn_attrs<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + llfn: &'ll Value, + instance: ty::Instance<'tcx>, +) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); match codegen_fn_attrs.optimize { @@ -322,7 +326,7 @@ .target_features .iter() .flat_map(|f| { - let feature = &f.as_str(); + let feature = f.as_str(); llvm_util::to_llvm_feature(cx.tcx.sess, feature) .into_iter() .map(|f| format!("+{}", f)) @@ -347,7 +351,7 @@ let name = codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id())); - let name = CString::new(&name.as_str()[..]).unwrap(); + let name = CString::new(name.as_str()).unwrap(); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/lto.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/lto.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/lto.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/lto.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,7 @@ }; use crate::llvm::archive_ro::ArchiveRO; use crate::llvm::{self, build_string, False, True}; -use crate::{LlvmCodegenBackend, ModuleLlvm}; +use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{ @@ -363,7 +363,7 @@ crate struct Linker<'a>(&'a mut llvm::Linker<'a>); -impl Linker<'a> { +impl<'a> Linker<'a> { crate fn new(llmod: &'a llvm::Module) -> Self { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } @@ -383,7 +383,7 @@ } } -impl Drop for Linker<'a> { +impl Drop for Linker<'_> { fn drop(&mut self) { unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); @@ -587,7 +587,7 @@ config: &ModuleConfig, thin: bool, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &module.name[..]); + let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name); // Now we have one massive module inside of llmod. Time to run the // LTO-specific optimization passes that LLVM provides. @@ -596,7 +596,10 @@ // tools/lto/LTOCodeGenerator.cpp debug!("running the pass manager"); unsafe { - if write::should_use_new_llvm_pass_manager(cgcx, config) { + if llvm_util::should_use_new_llvm_pass_manager( + &config.new_llvm_pass_manager, + &cgcx.target_arch, + ) { let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); write::optimize_with_new_llvm_pass_manager( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/write.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/write.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/write.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/back/write.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath}; +use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; @@ -46,7 +46,7 @@ } } -pub fn write_output_file( +pub fn write_output_file<'ll>( handler: &rustc_errors::Handler, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, @@ -106,7 +106,11 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { - tcx.output_filenames(()).split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name)) + tcx.output_filenames(()).split_dwarf_path( + tcx.sess.split_debuginfo(), + tcx.sess.opts.debugging_opts.split_dwarf_kind, + Some(mod_name), + ) } else { None }; @@ -205,8 +209,11 @@ let use_init_array = !sess.opts.debugging_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section); + let path_mapping = sess.source_map().path_mapping().clone(); + Arc::new(move |config: TargetMachineFactoryConfig| { - let split_dwarf_file = config.split_dwarf_file.unwrap_or_default(); + let split_dwarf_file = + path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap(); let tm = unsafe { @@ -259,6 +266,7 @@ pub struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), llcx: &'a llvm::Context, + old_handler: Option<&'a llvm::DiagnosticHandler>, } impl<'a> DiagnosticHandlers<'a> { @@ -267,12 +275,35 @@ handler: &'a Handler, llcx: &'a llvm::Context, ) -> Self { + let remark_passes_all: bool; + let remark_passes: Vec; + match &cgcx.remark { + Passes::All => { + remark_passes_all = true; + remark_passes = Vec::new(); + } + Passes::Some(passes) => { + remark_passes_all = false; + remark_passes = + passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect(); + } + }; + let remark_passes: Vec<*const c_char> = + remark_passes.iter().map(|name: &CString| name.as_ptr()).collect(); let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { + let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx); + llvm::LLVMRustContextConfigureDiagnosticHandler( + llcx, + diagnostic_handler, + data.cast(), + remark_passes_all, + remark_passes.as_ptr(), + remark_passes.len(), + ); llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast()); - llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast()); + DiagnosticHandlers { data, llcx, old_handler } } - DiagnosticHandlers { data, llcx } } } @@ -281,7 +312,7 @@ use std::ptr::null_mut; unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(self.llcx, inline_asm_handler, null_mut()); - llvm::LLVMContextSetDiagnosticHandler(self.llcx, diagnostic_handler, null_mut()); + llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler); drop(Box::from_raw(self.data)); } } @@ -337,13 +368,8 @@ if enabled { diag_handler.note_without_error(&format!( - "optimization {} for {} at {}:{}:{}: {}", - opt.kind.describe(), - opt.pass_name, - opt.filename, - opt.line, - opt.column, - opt.message + "{}:{}:{}: {}: {}", + opt.filename, opt.line, opt.column, opt.pass_name, opt.message, )); } } @@ -394,17 +420,6 @@ .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) } -pub(crate) fn should_use_new_llvm_pass_manager( - _cgcx: &CodegenContext, - config: &ModuleConfig, -) -> bool { - // The new pass manager is causing significant performance issues such as #91128, and is - // therefore disabled in stable versions of rustc by default. - config - .new_llvm_pass_manager - .unwrap_or(false) -} - pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( cgcx: &CodegenContext, diag_handler: &Handler, @@ -447,6 +462,8 @@ let extra_passes = config.passes.join(","); + let llvm_plugins = config.llvm_plugins.join(","); + // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. @@ -476,6 +493,8 @@ selfprofile_after_pass_callback, extra_passes.as_ptr().cast(), extra_passes.len(), + llvm_plugins.as_ptr().cast(), + llvm_plugins.len(), ); result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes")) } @@ -487,7 +506,7 @@ module: &ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &module.name[..]); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -504,7 +523,10 @@ } if let Some(opt_level) = config.opt_level { - if should_use_new_llvm_pass_manager(cgcx, config) { + if llvm_util::should_use_new_llvm_pass_manager( + &config.new_llvm_pass_manager, + &cgcx.target_arch, + ) { let opt_stage = match cgcx.lto { Lto::Fat => llvm::OptStage::PreLinkFatLTO, Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, @@ -640,14 +662,14 @@ { let _timer = cgcx.prof.extra_verbose_generic_activity( "LLVM_module_optimize_function_passes", - &module.name[..], + &*module.name, ); llvm::LLVMRustRunFunctionPassManager(fpm, llmod); } { let _timer = cgcx.prof.extra_verbose_generic_activity( "LLVM_module_optimize_module_passes", - &module.name[..], + &*module.name, ); llvm::LLVMRunPassManager(mpm, llmod); } @@ -710,7 +732,7 @@ module: ModuleCodegen, config: &ModuleConfig, ) -> Result { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); { let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -759,7 +781,7 @@ if config.bitcode_needed() { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name); let thin = ThinBuffer::new(llmod); let data = thin.data(); @@ -772,10 +794,9 @@ } if config.emit_bc || config.emit_obj == EmitObj::Bitcode { - let _timer = cgcx.prof.generic_activity_with_arg( - "LLVM_module_codegen_emit_bitcode", - &module.name[..], - ); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name); if let Err(e) = fs::write(&bc_out, data) { let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e); diag_handler.err(&msg); @@ -783,18 +804,16 @@ } if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { - let _timer = cgcx.prof.generic_activity_with_arg( - "LLVM_module_codegen_embed_bitcode", - &module.name[..], - ); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name); embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); } } if config.emit_ir { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); let out_c = path_to_c_string(&out); @@ -843,9 +862,8 @@ } if config.emit_asm { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and object code output, @@ -875,20 +893,21 @@ EmitObj::ObjectCode(_) => { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name); - let dwo_out = match cgcx.split_debuginfo { - // Don't change how DWARF is emitted in single mode (or when disabled). - SplitDebuginfo::Off | SplitDebuginfo::Packed => None, - // Emit (a subset of the) DWARF into a separate file in split mode. - SplitDebuginfo::Unpacked => { - if cgcx.target_can_use_split_dwarf { - Some(dwo_out.as_path()) - } else { - None - } - } + let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) { + // Don't change how DWARF is emitted when disabled. + (SplitDebuginfo::Off, _) => None, + // Don't provide a DWARF object path if split debuginfo is enabled but this is + // a platform that doesn't support Split DWARF. + _ if !cgcx.target_can_use_split_dwarf => None, + // Don't provide a DWARF object path in single mode, sections will be written + // into the object as normal but ignored by linker. + (_, SplitDwarfKind::Single) => None, + // Emit (a subset of the) DWARF into a separate dwarf object file in split + // mode. + (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; with_codegen(tm, llmod, config.no_builtins, |cpm| { @@ -925,12 +944,37 @@ Ok(module.into_compiled_module( config.emit_obj != EmitObj::None, - cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked, + cgcx.target_can_use_split_dwarf + && cgcx.split_debuginfo != SplitDebuginfo::Off + && cgcx.split_dwarf_kind == SplitDwarfKind::Split, config.emit_bc, &cgcx.output_filenames, )) } +fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: &[u8]) -> Vec { + let mut asm = format!(".section {},\"{}\"\n", section_name, section_flags).into_bytes(); + asm.extend_from_slice(b".ascii \""); + asm.reserve(data.len()); + for &byte in data { + if byte == b'\\' || byte == b'"' { + asm.push(b'\\'); + asm.push(byte); + } else if byte < 0x20 || byte >= 0x80 { + // Avoid non UTF-8 inline assembly. Use octal escape sequence, because it is fixed + // width, while hex escapes will consume following characters. + asm.push(b'\\'); + asm.push(b'0' + ((byte >> 6) & 0x7)); + asm.push(b'0' + ((byte >> 3) & 0x7)); + asm.push(b'0' + ((byte >> 0) & 0x7)); + } else { + asm.push(byte); + } + } + asm.extend_from_slice(b"\"\n"); + asm +} + /// Embed the bitcode of an LLVM module in the LLVM module itself. /// /// This is done primarily for iOS where it appears to be standard to compile C @@ -956,34 +1000,6 @@ cmdline: &str, bitcode: &[u8], ) { - let llconst = common::bytes_in_context(llcx, bitcode); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - "rustc.embedded.module\0".as_ptr().cast(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); - - let is_apple = cgcx.opts.target_triple.triple().contains("-ios") - || cgcx.opts.target_triple.triple().contains("-darwin") - || cgcx.opts.target_triple.triple().contains("-tvos"); - - let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::LLVMSetGlobalConstant(llglobal, llvm::True); - - let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - "rustc.embedded.cmdline\0".as_ptr().cast(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); - let section = if is_apple { "__LLVM,__cmdline\0" } else { ".llvmcmd\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - // We're adding custom sections to the output object file, but we definitely // do not want these custom sections to make their way into the final linked // executable. The purpose of these custom sections is for tooling @@ -1005,31 +1021,54 @@ // * COFF - if we don't do anything the linker will by default copy all // these sections to the output artifact, not what we want! To subvert // this we want to flag the sections we inserted here as - // `IMAGE_SCN_LNK_REMOVE`. Unfortunately though LLVM has no native way to - // do this. Thankfully though we can do this with some inline assembly, - // which is easy enough to add via module-level global inline asm. + // `IMAGE_SCN_LNK_REMOVE`. // // * ELF - this is very similar to COFF above. One difference is that these // sections are removed from the output linked artifact when // `--gc-sections` is passed, which we pass by default. If that flag isn't // passed though then these sections will show up in the final output. // Additionally the flag that we need to set here is `SHF_EXCLUDE`. + // + // Unfortunately, LLVM provides no way to set custom section flags. For ELF + // and COFF we emit the sections using module level inline assembly for that + // reason (see issue #90326 for historical background). + let is_apple = cgcx.opts.target_triple.triple().contains("-ios") + || cgcx.opts.target_triple.triple().contains("-darwin") + || cgcx.opts.target_triple.triple().contains("-tvos"); if is_apple || cgcx.opts.target_triple.triple().starts_with("wasm") || cgcx.opts.target_triple.triple().starts_with("asmjs") { - // nothing to do here - } else if cgcx.is_pe_coff { - let asm = " - .section .llvmbc,\"n\" - .section .llvmcmd,\"n\" - "; - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + // We don't need custom section flags, create LLVM globals. + let llconst = common::bytes_in_context(llcx, bitcode); + let llglobal = llvm::LLVMAddGlobal( + llmod, + common::val_ty(llconst), + "rustc.embedded.module\0".as_ptr().cast(), + ); + llvm::LLVMSetInitializer(llglobal, llconst); + + let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::LLVMSetGlobalConstant(llglobal, llvm::True); + + let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); + let llglobal = llvm::LLVMAddGlobal( + llmod, + common::val_ty(llconst), + "rustc.embedded.cmdline\0".as_ptr().cast(), + ); + llvm::LLVMSetInitializer(llglobal, llconst); + let section = if is_apple { "__LLVM,__cmdline\0" } else { ".llvmcmd\0" }; + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); } else { - let asm = " - .section .llvmbc,\"e\" - .section .llvmcmd,\"e\" - "; + // We need custom section flags, so emit module-level inline assembly. + let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; + let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); + llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/base.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,13 +9,12 @@ //! int)` and `rec(x=int, y=int, z=int)` will have the same [`llvm::Type`]. //! //! [`Ty`]: rustc_middle::ty::Ty -//! [`val_ty`]: common::val_ty +//! [`val_ty`]: crate::common::val_ty use super::ModuleLlvm; use crate::attributes; use crate::builder::Builder; -use crate::common; use crate::context::CodegenCx; use crate::llvm; use crate::value::Value; @@ -25,72 +24,22 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::middle::exported_symbols; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; use rustc_target::spec::SanitizerSet; -use std::ffi::CString; use std::time::Instant; -pub fn write_compressed_metadata<'tcx>( - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut ModuleLlvm, -) { - use snap::write::FrameEncoder; - use std::io::Write; - - // Historical note: - // - // When using link.exe it was seen that the section name `.note.rustc` - // was getting shortened to `.note.ru`, and according to the PE and COFF - // specification: - // - // > Executable images do not use a string table and do not support - // > section names longer than 8 characters - // - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - // - // As a result, we choose a slightly shorter name! As to why - // `.note.rustc` works on MinGW, see - // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 - let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" }; - - let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - - let llmeta = common::bytes_in_context(metadata_llcx, &compressed); - let llconst = common::struct_in_context(metadata_llcx, &[llmeta], false); - let name = exported_symbols::metadata_symbol_name(tcx); - let buf = CString::new(name).unwrap(); - let llglobal = - unsafe { llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr()) }; - unsafe { - llvm::LLVMSetInitializer(llglobal, llconst); - let name = SmallCStr::new(section_name); - llvm::LLVMSetSection(llglobal, name.as_ptr()); - - // Also generate a .section directive to force no - // flags, at least for ELF outputs, so that the - // metadata doesn't get loaded into memory. - let directive = format!(".section {}", section_name); - llvm::LLVMSetModuleInlineAsm2(metadata_llmod, directive.as_ptr().cast(), directive.len()) - } -} - pub struct ValueIter<'ll> { cur: Option<&'ll Value>, step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } -impl Iterator for ValueIter<'ll> { +impl<'ll> Iterator for ValueIter<'ll> { type Item = &'ll Value; fn next(&mut self) -> Option<&'ll Value> { @@ -102,14 +51,11 @@ } } -pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { +pub fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal } } } -pub fn compile_codegen_unit( - tcx: TyCtxt<'tcx>, - cgu_name: Symbol, -) -> (ModuleCodegen, u64) { +pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen, u64) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -133,7 +79,7 @@ &[cgu_name.to_string(), cgu.size_estimate().to_string()], ); // Instantiate monomorphizations without filling out definitions yet... - let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); + let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str()); { let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx); @@ -197,7 +143,7 @@ None => return, }; unsafe { - let buf = SmallCStr::new(§.as_str()); + let buf = SmallCStr::new(sect.as_str()); llvm::LLVMSetSection(llval, buf.as_ptr()); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/builder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/builder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/builder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/builder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -36,7 +36,7 @@ pub cx: &'a CodegenCx<'ll, 'tcx>, } -impl Drop for Builder<'a, 'll, 'tcx> { +impl Drop for Builder<'_, '_, '_> { fn drop(&mut self) { unsafe { llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); @@ -52,7 +52,7 @@ // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); -impl BackendTypes for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; type Function = as BackendTypes>::Function; type BasicBlock = as BackendTypes>::BasicBlock; @@ -70,27 +70,27 @@ } } -impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.cx.tcx } } -impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.cx.param_env() } } -impl HasTargetSpec for Builder<'_, '_, 'tcx> { +impl HasTargetSpec for Builder<'_, '_, '_> { #[inline] fn target_spec(&self) -> &Target { self.cx.target_spec() } } -impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; #[inline] @@ -99,7 +99,7 @@ } } -impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; #[inline] @@ -113,7 +113,7 @@ } } -impl Deref for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> Deref for Builder<'_, 'll, 'tcx> { type Target = CodegenCx<'ll, 'tcx>; #[inline] @@ -122,7 +122,7 @@ } } -impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> { type CodegenCx = CodegenCx<'ll, 'tcx>; } @@ -136,7 +136,7 @@ } } -impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { +impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self { let bx = Builder::with_cx(cx); unsafe { @@ -1201,19 +1201,26 @@ unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn do_not_inline(&mut self, llret: &'ll Value) { - llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) { + // Cleanup is always the cold path. + llvm::Attribute::Cold.apply_callsite(llvm::AttributePlace::Function, llret); + + // In LLVM versions with deferred inlining (currently, system LLVM < 14), + // inlining drop glue can lead to exponential size blowup, see #41696 and #92110. + if !llvm_util::is_rust_llvm() && llvm_util::get_version() < (14, 0, 0) { + llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); + } } } -impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { +impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { fn get_static(&mut self, def_id: DefId) -> &'ll Value { // Forward to the `get_static` method of `CodegenCx` self.cx().get_static(def_id) } } -impl Builder<'a, 'll, 'tcx> { +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/callee.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/callee.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/callee.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/callee.rs 2022-02-23 04:07:21.000000000 +0000 @@ -22,7 +22,7 @@ /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { +pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { let tcx = cx.tcx(); debug!("get_fn(instance={:?})", instance); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/common.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/common.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/common.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/common.rs 2022-02-23 04:07:21.000000000 +0000 @@ -65,7 +65,7 @@ operand: OperandBundleDef<'ll>, } -impl Funclet<'ll> { +impl<'ll> Funclet<'ll> { pub fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) } } @@ -79,7 +79,7 @@ } } -impl BackendTypes for CodegenCx<'ll, 'tcx> { +impl<'ll> BackendTypes for CodegenCx<'ll, '_> { type Value = &'ll Value; // FIXME(eddyb) replace this with a `Function` "subclass" of `Value`. type Function = &'ll Value; @@ -93,7 +93,7 @@ type DIVariable = &'ll llvm::debuginfo::DIVariable; } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) } } @@ -120,7 +120,7 @@ !null_terminated as Bool, ); let sym = self.generate_local_symbol_name("str"); - let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(|| { + let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| { bug!("symbol `{}` is already defined", sym); }); llvm::LLVMSetInitializer(g, sc); @@ -145,7 +145,7 @@ } } -impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn const_null(&self, t: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstNull(t) } } @@ -327,14 +327,18 @@ unsafe { llvm::LLVMTypeOf(v) } } -pub fn bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { +pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True) } } -pub fn struct_in_context(llcx: &'a llvm::Context, elts: &[&'a Value], packed: bool) -> &'a Value { +pub fn struct_in_context<'ll>( + llcx: &'ll llvm::Context, + elts: &[&'ll Value], + packed: bool, +) -> &'ll Value { unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, packed as Bool) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/consts.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/consts.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/consts.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/consts.rs 2022-02-23 04:07:21.000000000 +0000 @@ -24,7 +24,7 @@ use std::ops::Range; use tracing::debug; -pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { +pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; @@ -127,7 +127,7 @@ cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer( +pub fn codegen_static_initializer<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { @@ -135,7 +135,7 @@ Ok((const_alloc_to_llvm(cx, alloc), alloc)) } -fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) { +fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. @@ -152,7 +152,7 @@ } } -fn check_and_apply_linkage( +fn check_and_apply_linkage<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, @@ -206,11 +206,11 @@ } } -pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { +pub fn ptrcast<'ll>(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstPointerCast(val, ty) } } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { crate fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstBitCast(val, ty) } } @@ -225,7 +225,7 @@ let gv = match kind { Some(kind) if !self.tcx.sess.fewer_names() => { let name = self.generate_local_symbol_name(kind); - let gv = self.define_global(&name[..], self.val_ty(cv)).unwrap_or_else(|| { + let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| { bug!("symbol `{}` is already defined", name); }); llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); @@ -344,7 +344,7 @@ } } -impl StaticMethods for CodegenCx<'ll, 'tcx> { +impl<'ll> StaticMethods for CodegenCx<'ll, '_> { fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { if let Some(&gv) = self.const_globals.borrow().get(&cv) { unsafe { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/context.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/context.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/context.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/context.rs 2022-02-23 04:07:21.000000000 +0000 @@ -124,7 +124,7 @@ } } -pub unsafe fn create_module( +pub unsafe fn create_module<'ll>( tcx: TyCtxt<'_>, llcx: &'ll llvm::Context, mod_name: &str, @@ -320,7 +320,7 @@ let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(tcx, &codegen_unit.name().as_str(), &dctx); + debuginfo::metadata::compile_unit_metadata(tcx, codegen_unit.name().as_str(), &dctx); Some(dctx) } else { None @@ -363,7 +363,7 @@ } #[inline] - pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> { + pub fn coverage_context(&self) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } @@ -380,7 +380,7 @@ } } -impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn vtables( &self, ) -> &RefCell, Option>), &'ll Value>> @@ -504,8 +504,8 @@ } } -impl CodegenCx<'b, 'tcx> { - crate fn get_intrinsic(&self, key: &str) -> (&'b Type, &'b Value) { +impl<'ll> CodegenCx<'ll, '_> { + crate fn get_intrinsic(&self, key: &str) -> (&'ll Type, &'ll Value) { if let Some(v) = self.intrinsics.borrow().get(key).cloned() { return v; } @@ -516,9 +516,9 @@ fn insert_intrinsic( &self, name: &'static str, - args: Option<&[&'b llvm::Type]>, - ret: &'b llvm::Type, - ) -> (&'b llvm::Type, &'b llvm::Value) { + args: Option<&[&'ll llvm::Type]>, + ret: &'ll llvm::Type, + ) -> (&'ll llvm::Type, &'ll llvm::Value) { let fn_ty = if let Some(args) = args { self.type_func(args, ret) } else { @@ -529,7 +529,7 @@ (fn_ty, f) } - fn declare_intrinsic(&self, key: &str) -> Option<(&'b Type, &'b Value)> { + fn declare_intrinsic(&self, key: &str) -> Option<(&'ll Type, &'ll Value)> { macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( if key == $name { @@ -793,7 +793,7 @@ None } - crate fn eh_catch_typeinfo(&self) -> &'b Value { + crate fn eh_catch_typeinfo(&self) -> &'ll Value { if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() { return eh_catch_typeinfo; } @@ -813,7 +813,7 @@ } } -impl<'b, 'tcx> CodegenCx<'b, 'tcx> { +impl CodegenCx<'_, '_> { /// Generates a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. pub fn generate_local_symbol_name(&self, prefix: &str) -> String { @@ -829,21 +829,21 @@ } } -impl HasDataLayout for CodegenCx<'ll, 'tcx> { +impl HasDataLayout for CodegenCx<'_, '_> { #[inline] fn data_layout(&self) -> &TargetDataLayout { &self.tcx.data_layout } } -impl HasTargetSpec for CodegenCx<'ll, 'tcx> { +impl HasTargetSpec for CodegenCx<'_, '_> { #[inline] fn target_spec(&self) -> &Target { &self.tcx.sess.target } } -impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx @@ -856,7 +856,7 @@ } } -impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; #[inline] @@ -869,7 +869,7 @@ } } -impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; #[inline] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,6 +9,7 @@ use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_llvm::RustString; use rustc_middle::mir::coverage::CodeRegion; +use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; use std::ffi::CString; @@ -17,10 +18,11 @@ /// Generates and exports the Coverage Map. /// -/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3), -/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format) -/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM -/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM. +/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions +/// 5 (LLVM 12, only) and 6 (zero-based encoded as 4 and 5, respectively), as defined at +/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). +/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`) +/// bundled with Rust's fork of LLVM. /// /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with /// the same version. Clang's implementation of Coverage Map generation was referenced when @@ -30,11 +32,12 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { let tcx = cx.tcx; - // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3). - // If not, the LLVM Version must be less than 11. + // Ensure the installed version of LLVM supports at least Coverage Map + // Version 5 (encoded as a zero-based value: 4), which was introduced with + // LLVM 12. let version = coverageinfo::mapping_version(); - if version != 3 { - tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher."); + if version < 4 { + tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 12 or higher."); } debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); @@ -57,7 +60,7 @@ return; } - let mut mapgen = CoverageMapGenerator::new(); + let mut mapgen = CoverageMapGenerator::new(tcx, version); // Encode coverage mappings and generate function records let mut function_data = Vec::new(); @@ -86,7 +89,7 @@ }); let filenames_size = filenames_buffer.len(); - let filenames_val = cx.const_bytes(&filenames_buffer[..]); + let filenames_val = cx.const_bytes(&filenames_buffer); let filenames_ref = coverageinfo::hash_bytes(filenames_buffer); // Generate the LLVM IR representation of the coverage map and store it in a well-known global @@ -112,15 +115,33 @@ } impl CoverageMapGenerator { - fn new() -> Self { - Self { filenames: FxIndexSet::default() } + fn new(tcx: TyCtxt<'_>, version: u32) -> Self { + let mut filenames = FxIndexSet::default(); + if version >= 5 { + // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) + // requires setting the first filename to the compilation directory. + // Since rustc generates coverage maps with relative paths, the + // compilation directory can be combined with the the relative paths + // to get absolute paths, if needed. + let working_dir = tcx + .sess + .opts + .working_dir + .remapped_path_if_available() + .to_string_lossy() + .to_string(); + let c_filename = + CString::new(working_dir).expect("null error converting filename to C string"); + filenames.insert(c_filename); + } + Self { filenames } } /// Using the `expressions` and `counter_regions` collected for the current function, generate /// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use /// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into /// the given `coverage_mapping` byte buffer, compliant with the LLVM Coverage Mapping format. - fn write_coverage_mapping( + fn write_coverage_mapping<'a>( &mut self, expressions: Vec, counter_regions: impl Iterator, @@ -179,9 +200,9 @@ /// Construct coverage map header and the array of function records, and combine them into the /// coverage map. Save the coverage map data into the LLVM IR as a static global using a /// specific, well-known section and name. - fn generate_coverage_map( + fn generate_coverage_map<'ll>( self, - cx: &CodegenCx<'ll, 'tcx>, + cx: &CodegenCx<'ll, '_>, version: u32, filenames_size: usize, filenames_val: &'ll llvm::Value, @@ -208,7 +229,7 @@ /// Save the function record into the LLVM IR as a static global using a /// specific, well-known section and name. fn save_function_record( - cx: &CodegenCx<'ll, 'tcx>, + cx: &CodegenCx<'_, '_>, mangled_function_name: String, source_hash: u64, filenames_ref: u64, @@ -217,7 +238,7 @@ ) { // Concatenate the encoded coverage mappings let coverage_mapping_size = coverage_mapping_buffer.len(); - let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer[..]); + let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer); let func_name_hash = coverageinfo::hash_str(&mangled_function_name); let func_name_hash_val = cx.const_u64(func_name_hash); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -56,7 +56,7 @@ } } -impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn coverageinfo_finalize(&self) { mapgen::finalize(self) } @@ -96,7 +96,7 @@ } } -impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -184,7 +184,7 @@ } } -fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx> { +fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: &DefId) -> Instance<'tcx> { let tcx = cx.tcx; let instance = Instance::new( @@ -212,15 +212,15 @@ ), ); - llvm::set_linkage(llfn, llvm::Linkage::WeakAnyLinkage); - llvm::set_visibility(llfn, llvm::Visibility::Hidden); + llvm::set_linkage(llfn, llvm::Linkage::PrivateLinkage); + llvm::set_visibility(llfn, llvm::Visibility::Default); assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none()); instance } -fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { +fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { let llfn = cx.get_fn(instance); let llbb = Builder::append_block(cx, llfn, "unused_function"); let mut bx = Builder::build(cx, llbb); @@ -237,8 +237,8 @@ bx.ret_void(); } -fn add_unused_function_coverage( - cx: &CodegenCx<'ll, 'tcx>, +fn add_unused_function_coverage<'tcx>( + cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, def_id: DefId, ) { @@ -268,7 +268,7 @@ /// required by LLVM InstrProf source-based coverage instrumentation. Use /// `bx.get_pgo_func_name_var()` to ensure the variable is only created once per /// `Instance`. -fn create_pgo_func_name_var( +fn create_pgo_func_name_var<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, ) -> &'ll llvm::Value { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,7 +16,7 @@ /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. -pub fn compute_mir_scopes( +pub fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, @@ -45,7 +45,7 @@ } } -fn make_mir_scope( +fn make_mir_scope<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs 2022-02-23 04:07:21.000000000 +0000 @@ -28,7 +28,7 @@ /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) -> &'ll Value { +pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Value { let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0"; let section_var_name = &c_section_var_name[..c_section_var_name.len() - 1]; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,6 +18,7 @@ use crate::value::Value; use cstr::cstr; +use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -155,7 +156,7 @@ type_to_unique_id: FxHashMap, UniqueTypeId>, } -impl TypeMap<'ll, 'tcx> { +impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if /// the mapping already exists. fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) { @@ -291,7 +292,7 @@ FinalMetadata(&'ll DICompositeType), } -fn create_and_register_recursive_type_forward_declaration( +fn create_and_register_recursive_type_forward_declaration<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -313,7 +314,7 @@ } } -impl RecursiveTypeDescription<'ll, 'tcx> { +impl<'ll, 'tcx> RecursiveTypeDescription<'ll, 'tcx> { /// Finishes up the description of the type in question (mostly by providing /// descriptions of the fields of the given type) and returns the final type /// metadata. @@ -375,7 +376,7 @@ }; } -fn fixed_vec_metadata( +fn fixed_vec_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, array_or_slice_type: Ty<'tcx>, @@ -410,7 +411,7 @@ MetadataCreationResult::new(metadata, false) } -fn vec_slice_metadata( +fn vec_slice_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, slice_ptr_type: Ty<'tcx>, element_type: Ty<'tcx>, @@ -456,7 +457,7 @@ let metadata = composite_type_metadata( cx, slice_ptr_type, - &slice_type_name[..], + &slice_type_name, unique_type_id, member_descriptions, NO_SCOPE_METADATA, @@ -466,7 +467,7 @@ MetadataCreationResult::new(metadata, false) } -fn subroutine_type_metadata( +fn subroutine_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, signature: ty::PolyFnSig<'tcx>, @@ -507,7 +508,7 @@ // `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part // of a DST struct, there is no `trait_object_type` and the results of this // function will be a little bit weird. -fn trait_pointer_metadata( +fn trait_pointer_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, trait_type: Ty<'tcx>, trait_object_type: Option>, @@ -579,7 +580,7 @@ composite_type_metadata( cx, trait_object_type.unwrap_or(trait_type), - &trait_type_name[..], + &trait_type_name, unique_type_id, member_descriptions, containing_scope, @@ -588,7 +589,11 @@ ) } -pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Span) -> &'ll DIType { +pub fn type_metadata<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + usage_site_span: Span, +) -> &'ll DIType { // Get the unique type ID of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -812,7 +817,7 @@ hex_string } -pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { +pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { debug!("file_metadata: file_name: {:?}", source_file.name); let hash = Some(&source_file.src_hash); @@ -833,11 +838,11 @@ file_metadata_raw(cx, file_name, directory, hash) } -pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { +pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { file_metadata_raw(cx, None, None, None) } -fn file_metadata_raw( +fn file_metadata_raw<'ll>( cx: &CodegenCx<'ll, '_>, file_name: Option, directory: Option, @@ -924,21 +929,21 @@ } } -fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); // When targeting MSVC, emit MSVC style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let msvc_like_names = cx.tcx.sess.target.is_like_msvc; + let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx); let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), - ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed), - ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), - ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float), + ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed), + ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), + ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float), ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed), ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned), ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float), @@ -955,7 +960,7 @@ ) }; - if !msvc_like_names { + if !cpp_like_debuginfo { return ty_metadata; } @@ -981,7 +986,7 @@ typedef_metadata } -fn foreign_type_metadata( +fn foreign_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -992,7 +997,7 @@ create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) } -fn pointer_type_metadata( +fn pointer_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointer_type: Ty<'tcx>, pointee_type_metadata: &'ll DIType, @@ -1012,7 +1017,7 @@ } } -fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("param_type_metadata: {:?}", t); let name = format!("{:?}", t); unsafe { @@ -1026,24 +1031,35 @@ } } -pub fn compile_unit_metadata( - tcx: TyCtxt<'_>, +pub fn compile_unit_metadata<'ll, 'tcx>( + tcx: TyCtxt<'tcx>, codegen_unit_name: &str, - debug_context: &CrateDebugContext<'ll, '_>, + debug_context: &CrateDebugContext<'ll, 'tcx>, ) -> &'ll DIDescriptor { let mut name_in_debuginfo = match tcx.sess.local_crate_source_file { Some(ref path) => path.clone(), - None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()), + None => PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()), }; - // The OSX linker has an idiosyncrasy where it will ignore some debuginfo - // if multiple object files with the same `DW_AT_name` are linked together. - // As a workaround we generate unique names for each object file. Those do - // not correspond to an actual source file but that is harmless. - if tcx.sess.target.is_like_osx { - name_in_debuginfo.push("@"); - name_in_debuginfo.push(codegen_unit_name); - } + // To avoid breaking split DWARF, we need to ensure that each codegen unit + // has a unique `DW_AT_name`. This is because there's a remote chance that + // different codegen units for the same module will have entirely + // identical DWARF entries for the purpose of the DWO ID, which would + // violate Appendix F ("Split Dwarf Object Files") of the DWARF 5 + // specification. LLVM uses the algorithm specified in section 7.32 "Type + // Signature Computation" to compute the DWO ID, which does not include + // any fields that would distinguish compilation units. So we must embed + // the codegen unit name into the `DW_AT_name`. (Issue #88521.) + // + // Additionally, the OSX linker has an idiosyncrasy where it will ignore + // some debuginfo if multiple object files with the same `DW_AT_name` are + // linked together. + // + // As a workaround for these two issues, we generate unique names for each + // object file. Those do not correspond to an actual source file but that + // is harmless. + name_in_debuginfo.push("@"); + name_in_debuginfo.push(codegen_unit_name); debug!("compile_unit_metadata: {:?}", name_in_debuginfo); let rustc_producer = @@ -1055,11 +1071,15 @@ let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped); let flags = "\0"; let output_filenames = tcx.output_filenames(()); - let out_dir = &output_filenames.out_directory; let split_name = if tcx.sess.target_can_use_split_dwarf() { output_filenames - .split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name)) - .map(|f| out_dir.join(f)) + .split_dwarf_path( + tcx.sess.split_debuginfo(), + tcx.sess.opts.debugging_opts.split_dwarf_kind, + Some(codegen_unit_name), + ) + // We get a path relative to the working directory from split_dwarf_path + .map(|f| tcx.sess.source_map().path_mapping().map_prefix(f).0) } else { None } @@ -1159,7 +1179,7 @@ return unit_metadata; }; - fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { + fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { let path_str = path_to_c_string(path); unsafe { llvm::LLVMMDStringInContext( @@ -1176,7 +1196,7 @@ already_stored_in_typemap: bool, } -impl MetadataCreationResult<'ll> { +impl<'ll> MetadataCreationResult<'ll> { fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self { MetadataCreationResult { metadata, already_stored_in_typemap } } @@ -1243,7 +1263,7 @@ VariantMDF(VariantMemberDescriptionFactory<'tcx>), } -impl MemberDescriptionFactory<'ll, 'tcx> { +impl<'ll, 'tcx> MemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { match *self { StructMDF(ref this) => this.create_member_descriptions(cx), @@ -1267,7 +1287,10 @@ } impl<'tcx> StructMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { let layout = cx.layout_of(self.ty); self.variant .fields @@ -1295,7 +1318,7 @@ } } -fn prepare_struct_metadata( +fn prepare_struct_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -1338,7 +1361,7 @@ /// Here are some examples: /// - `name__field1__field2` when the upvar is captured by value. /// - `_ref__name__field` when the upvar is captured by reference. -fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec { +fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> Vec { let body = tcx.optimized_mir(def_id); body.var_debug_info @@ -1353,7 +1376,7 @@ _ => return None, }; let prefix = if is_ref { "_ref__" } else { "" }; - Some(prefix.to_owned() + &var.name.as_str()) + Some(prefix.to_owned() + var.name.as_str()) }) .collect::>() } @@ -1366,7 +1389,10 @@ } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { let mut capture_names = match *self.ty.kind() { ty::Generator(def_id, ..) | ty::Closure(def_id, ..) => { Some(closure_saved_names_of_captured_variables(cx.tcx, def_id).into_iter()) @@ -1399,7 +1425,7 @@ } } -fn prepare_tuple_metadata( +fn prepare_tuple_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, tuple_type: Ty<'tcx>, component_types: &[Ty<'tcx>], @@ -1443,7 +1469,10 @@ } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { self.variant .fields .iter() @@ -1465,7 +1494,7 @@ } } -fn prepare_union_metadata( +fn prepare_union_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -1497,16 +1526,9 @@ // Enums //=----------------------------------------------------------------------------- -/// DWARF variant support is only available starting in LLVM 8, but -/// on MSVC we have to use the fallback mode, because LLVM doesn't -/// lower variant parts to PDB. -fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { - cx.sess().target.is_like_msvc -} - // FIXME(eddyb) maybe precompute this? Right now it's computed once // per generator monomorphization, but it doesn't depend on substs. -fn generator_layout_and_saved_local_names( +fn generator_layout_and_saved_local_names<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> (&'tcx GeneratorLayout<'tcx>, IndexVec>) { @@ -1525,14 +1547,12 @@ // Deref of the `Pin<&mut Self>` state argument. mir::ProjectionElem::Field(..), mir::ProjectionElem::Deref, - // Field of a variant of the state. mir::ProjectionElem::Downcast(_, variant), mir::ProjectionElem::Field(field, _), ] => { - let name = &mut generator_saved_local_names[ - generator_layout.variant_fields[variant][field] - ]; + let name = &mut generator_saved_local_names + [generator_layout.variant_fields[variant][field]]; if name.is_none() { name.replace(var.name); } @@ -1556,7 +1576,7 @@ span: Span, } -impl EnumMemberDescriptionFactory<'ll, 'tcx> { +impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { let generator_variant_info_data = match *self.enum_type.kind() { ty::Generator(def_id, ..) => { @@ -1580,7 +1600,10 @@ _ => bug!(), }; - let fallback = use_enum_fallback(cx); + // While LLVM supports generating debuginfo for variant types (enums), it doesn't support + // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting + // msvc, then we need to use a different, fallback encoding of the debuginfo. + let fallback = cpp_like_debuginfo(cx.tcx); // This will always find the metadata in the type map. let self_metadata = type_metadata(cx, self.enum_type, self.span); @@ -1888,8 +1911,11 @@ span: Span, } -impl VariantMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { +impl<'tcx> VariantMemberDescriptionFactory<'tcx> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { self.args .iter() .enumerate() @@ -1924,7 +1950,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> { fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { match self { - VariantInfo::Adt(variant) => f(&variant.ident.as_str()), + VariantInfo::Adt(variant) => f(variant.ident.as_str()), VariantInfo::Generator { variant_index, .. } => { f(&GeneratorSubsts::variant_name(*variant_index)) } @@ -1963,7 +1989,7 @@ field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) } - fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { + fn source_info<'ll>(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { if let VariantInfo::Generator { def_id, variant_index, .. } = self { let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info[*variant_index].span; @@ -1980,7 +2006,7 @@ /// `MemberDescriptionFactory` for producing the descriptions of the /// fields of the variant. This is a rudimentary version of a full /// `RecursiveTypeDescription`. -fn describe_enum_variant( +fn describe_enum_variant<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, @@ -2013,7 +2039,7 @@ (metadata_stub, member_description_factory) } -fn prepare_enum_metadata( +fn prepare_enum_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type: Ty<'tcx>, enum_def_id: DefId, @@ -2089,8 +2115,8 @@ let item_name; let discriminant_name = match enum_type.kind() { ty::Adt(..) => { - item_name = tcx.item_name(enum_def_id).as_str(); - &*item_name + item_name = tcx.item_name(enum_def_id); + item_name.as_str() } ty::Generator(..) => enum_name.as_str(), _ => bug!(), @@ -2130,7 +2156,10 @@ return FinalMetadata(discriminant_type_metadata(tag.value)); } - if use_enum_fallback(cx) { + // While LLVM supports generating debuginfo for variant types (enums), it doesn't support + // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting + // msvc, then we need to use a different encoding of the debuginfo. + if cpp_like_debuginfo(tcx) { let discriminant_type_metadata = match layout.variants { Variants::Single { .. } => None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } @@ -2332,7 +2361,7 @@ /// results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn composite_type_metadata( +fn composite_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, composite_type: Ty<'tcx>, composite_type_name: &str, @@ -2366,7 +2395,7 @@ composite_type_metadata } -fn set_members_of_composite_type( +fn set_members_of_composite_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, @@ -2400,7 +2429,7 @@ let type_params = compute_type_parameters(cx, composite_type); unsafe { - let type_array = create_DIArray(DIB(cx), &member_metadata[..]); + let type_array = create_DIArray(DIB(cx), &member_metadata); llvm::LLVMRustDICompositeTypeReplaceArrays( DIB(cx), composite_type_metadata, @@ -2411,7 +2440,7 @@ } /// Computes the type parameters for a type, if any, for the given metadata. -fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { +fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { if let ty::Adt(def, substs) = *ty.kind() { if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); @@ -2423,7 +2452,7 @@ cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, rustc_span::DUMMY_SP); - let name = &name.as_str(); + let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -2439,7 +2468,7 @@ }) .collect(); - return create_DIArray(DIB(cx), &template_params[..]); + return create_DIArray(DIB(cx), &template_params); } } return create_DIArray(DIB(cx), &[]); @@ -2456,7 +2485,7 @@ /// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do /// any caching, does not add any fields to the struct. This can be done later /// with `set_members_of_composite_type()`. -fn create_struct_stub( +fn create_struct_stub<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, struct_type_name: &str, @@ -2497,7 +2526,7 @@ metadata_stub } -fn create_union_stub( +fn create_union_stub<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, union_type_name: &str, @@ -2538,7 +2567,7 @@ /// Creates debug information for the given global variable. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { +pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { if cx.dbg_cx.is_none() { return; } @@ -2565,7 +2594,8 @@ let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = tcx.item_name(def_id).as_str(); + let var_name = tcx.item_name(def_id); + let var_name = var_name.as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; // When empty, linkage_name field is omitted, // which is what we want for no_mangle statics @@ -2593,7 +2623,7 @@ } /// Generates LLVM debuginfo for a vtable. -fn vtable_type_metadata( +fn vtable_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option>, @@ -2625,7 +2655,7 @@ /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_metadata( +pub fn create_vtable_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option>, @@ -2664,7 +2694,7 @@ } /// Creates an "extension" of an existing `DIScope` into another file. -pub fn extend_scope_to_file( +pub fn extend_scope_to_file<'ll>( cx: &CodegenCx<'ll, '_>, scope_metadata: &'ll DIScope, file: &SourceFile, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -71,7 +71,7 @@ composite_types_completed: RefCell>, } -impl Drop for CrateDebugContext<'a, 'tcx> { +impl Drop for CrateDebugContext<'_, '_> { fn drop(&mut self) { unsafe { llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _)); @@ -144,7 +144,7 @@ } } -impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { +impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( @@ -160,17 +160,17 @@ // the values should match the ones in the DWARF standard anyway. let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }; let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }; - let mut addr_ops = SmallVec::<[_; 8]>::new(); + let mut addr_ops = SmallVec::<[u64; 8]>::new(); if direct_offset.bytes() > 0 { addr_ops.push(op_plus_uconst()); - addr_ops.push(direct_offset.bytes() as i64); + addr_ops.push(direct_offset.bytes() as u64); } for &offset in indirect_offsets { addr_ops.push(op_deref()); if offset.bytes() > 0 { addr_ops.push(op_plus_uconst()); - addr_ops.push(offset.bytes() as i64); + addr_ops.push(offset.bytes() as u64); } } @@ -236,7 +236,7 @@ pub col: u32, } -impl CodegenCx<'ll, '_> { +impl CodegenCx<'_, '_> { /// Looks up debug source information about a `BytePos`. // FIXME(eddyb) rename this to better indicate it's a duplicate of // `lookup_char_pos` rather than `dbg_loc`, perhaps by making @@ -266,7 +266,7 @@ } } -impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn create_function_debug_context( &self, instance: Instance<'tcx>, @@ -474,7 +474,7 @@ vec![] }; - create_DIArray(DIB(cx), &template_params[..]) + create_DIArray(DIB(cx), &template_params) } fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,7 +17,7 @@ tcx.symbol_name(instance) } -pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,21 +23,26 @@ } #[allow(non_snake_case)] -pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray { +pub fn create_DIArray<'ll>( + builder: &DIBuilder<'ll>, + arr: &[Option<&'ll DIDescriptor>], +) -> &'ll DIArray { unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) } } #[inline] -pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> { +pub fn debug_context<'a, 'll, 'tcx>( + cx: &'a CodegenCx<'ll, 'tcx>, +) -> &'a CrateDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() } #[inline] #[allow(non_snake_case)] -pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { +pub fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id).expect("get_namespace_for_item: missing parent?")) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/declare.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/declare.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/declare.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/declare.rs 2022-02-23 04:07:21.000000000 +0000 @@ -26,7 +26,7 @@ /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -fn declare_raw_fn( +fn declare_raw_fn<'ll>( cx: &CodegenCx<'ll, '_>, name: &str, callconv: llvm::CallConv, @@ -50,7 +50,7 @@ llfn } -impl CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Declare a global value. /// /// If there’s a value with the same name already declared, the function will diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs 2022-02-23 04:07:21.000000000 +0000 @@ -25,7 +25,10 @@ use std::cmp::Ordering; use std::iter; -fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<(&'ll Type, &'ll Value)> { +fn get_simple_intrinsic<'ll>( + cx: &CodegenCx<'ll, '_>, + name: Symbol, +) -> Option<(&'ll Type, &'ll Value)> { let llvm_name = match name { sym::sqrtf32 => "llvm.sqrt.f32", sym::sqrtf64 => "llvm.sqrt.f64", @@ -74,7 +77,7 @@ Some(cx.get_intrinsic(llvm_name)) } -impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, @@ -350,6 +353,8 @@ false, ast::LlvmAsmDialect::Att, &[span], + false, + None, ) .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`")); @@ -409,8 +414,8 @@ } } -fn try_intrinsic( - bx: &mut Builder<'a, 'll, 'tcx>, +fn try_intrinsic<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -439,8 +444,8 @@ // instructions are meant to work for all targets, as of the time of this // writing, however, LLVM does not recommend the usage of these new instructions // as the old ones are still more optimized. -fn codegen_msvc_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_msvc_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -591,8 +596,8 @@ // function calling it, and that function may already have other personality // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. -fn codegen_gnu_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_gnu_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -647,8 +652,8 @@ // Variant of codegen_gnu_try used for emscripten where Rust panics are // implemented using C++ exceptions. Here we use exceptions of a specific type // (`struct rust_panic`) to represent Rust panics. -fn codegen_emcc_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_emcc_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -797,8 +802,8 @@ rust_try } -fn generic_simd_intrinsic( - bx: &mut Builder<'a, 'll, 'tcx>, +fn generic_simd_intrinsic<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, &'ll Value>], @@ -1127,12 +1132,12 @@ } } - fn simd_simple_float_intrinsic( + fn simd_simple_float_intrinsic<'ll, 'tcx>( name: Symbol, in_elem: &::rustc_middle::ty::TyS<'_>, in_ty: &::rustc_middle::ty::TyS<'_>, in_len: u64, - bx: &mut Builder<'a, 'll, 'tcx>, + bx: &mut Builder<'_, 'll, 'tcx>, span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { @@ -1230,7 +1235,7 @@ elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize, - bx: &Builder<'a, 'll, 'tcx>, + bx: &Builder<'_, '_, '_>, ) -> String { let p0s: String = "p0".repeat(no_pointers); match *elem_ty.kind() { @@ -1253,7 +1258,7 @@ } } - fn llvm_vector_ty( + fn llvm_vector_ty<'ll>( cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: u64, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,11 +6,8 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] -#![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] #![feature(extern_types)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(nll)] #![recursion_limit = "256"] @@ -102,14 +99,6 @@ ModuleLlvm::new_metadata(tcx, mod_name) } - fn write_compressed_metadata<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut ModuleLlvm, - ) { - base::write_compressed_metadata(tcx, metadata, llvm_module) - } fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, @@ -348,6 +337,7 @@ &self, ongoing_codegen: Box, sess: &Session, + outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported> { let (codegen_results, work_products) = ongoing_codegen .downcast::>() @@ -356,7 +346,8 @@ sess.time("llvm_dump_timing_file", || { if sess.opts.debugging_opts.llvm_time_trace { - llvm_util::time_trace_profiler_finish("llvm_timings.json"); + let file_name = outputs.with_extension("llvm_timings.json"); + llvm_util::time_trace_profiler_finish(&file_name); } }); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs 2022-02-23 04:07:21.000000000 +0000 @@ -43,7 +43,7 @@ pub message: String, } -impl OptimizationDiagnostic<'ll> { +impl<'ll> OptimizationDiagnostic<'ll> { unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> Self { let mut function = None; let mut line = 0; @@ -142,7 +142,7 @@ } impl InlineAsmDiagnostic { - unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self { + unsafe fn unpackInlineAsm(di: &DiagnosticInfo) -> Self { let mut cookie = 0; let mut message = None; let mut level = super::DiagnosticLevel::Error; @@ -157,7 +157,7 @@ } } - unsafe fn unpackSrcMgr(di: &'ll DiagnosticInfo) -> Self { + unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self { let mut cookie = 0; let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)); InlineAsmDiagnostic { @@ -180,7 +180,7 @@ UnknownDiagnostic(&'ll DiagnosticInfo), } -impl Diagnostic<'ll> { +impl<'ll> Diagnostic<'ll> { pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; let kind = super::LLVMRustGetDiagInfoKind(di); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs 2022-02-23 04:07:21.000000000 +0000 @@ -675,13 +675,17 @@ #[repr(C)] pub struct Linker<'a>(InvariantOpaque<'a>); -pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); -pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); +extern "C" { + pub type DiagnosticHandler; +} + +pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); pub mod coverageinfo { use super::coverage_map; - /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222) + /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum RegionKind { @@ -700,11 +704,16 @@ /// A GapRegion is like a CodeRegion, but its count is only set as the /// line execution count when its the only region in the line. GapRegion = 3, + + /// A BranchRegion represents leaf-level boolean expressions and is + /// associated with two counters, each representing the number of times the + /// expression evaluates to true or false. + BranchRegion = 4, } /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the /// coverage map, in accordance with the - /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). + /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). /// The struct composes fields representing the `Counter` type and value(s) (injected counter /// ID, or expression type and operands), the source file (an indirect index into a "filenames /// array", encoded separately), and source location (start and end positions of the represented @@ -717,6 +726,10 @@ /// The counter type and type-dependent counter data, if any. counter: coverage_map::Counter, + /// If the `RegionKind` is a `BranchRegion`, this represents the counter + /// for the false branch of the region. + false_counter: coverage_map::Counter, + /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes /// that, in turn, are used to look up the filename for this region. @@ -754,6 +767,7 @@ ) -> Self { Self { counter, + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -767,6 +781,31 @@ // This function might be used in the future; the LLVM API is still evolving, as is coverage // support. #[allow(dead_code)] + crate fn branch_region( + counter: coverage_map::Counter, + false_counter: coverage_map::Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter, + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::BranchRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] crate fn expansion_region( file_id: u32, expanded_file_id: u32, @@ -777,6 +816,7 @@ ) -> Self { Self { counter: coverage_map::Counter::zero(), + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id, start_line, @@ -799,6 +839,7 @@ ) -> Self { Self { counter: coverage_map::Counter::zero(), + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -822,6 +863,7 @@ ) -> Self { Self { counter, + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -971,17 +1013,17 @@ pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type; // Operations on function types - pub fn LLVMFunctionType( + pub fn LLVMFunctionType<'a>( ReturnType: &'a Type, ParamTypes: *const &'a Type, ParamCount: c_uint, IsVarArg: Bool, ) -> &'a Type; pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint; - pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type); + pub fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type); // Operations on struct types - pub fn LLVMStructTypeInContext( + pub fn LLVMStructTypeInContext<'a>( C: &'a Context, ElementTypes: *const &'a Type, ElementCount: c_uint, @@ -1004,10 +1046,10 @@ pub fn LLVMTypeOf(Val: &Value) -> &Type; pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char; pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); - pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); - pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); - pub fn LLVMGlobalSetMetadata(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); - pub fn LLVMValueAsMetadata(Node: &'a Value) -> &Metadata; + pub fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value); + pub fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value); + pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); + pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata; // Operations on constants of any type pub fn LLVMConstNull(Ty: &Type) -> &Value; @@ -1015,8 +1057,12 @@ // Operations on metadata pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; - pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value; - pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value); + pub fn LLVMMDNodeInContext<'a>( + C: &'a Context, + Vals: *const &'a Value, + Count: c_uint, + ) -> &'a Value; + pub fn LLVMAddNamedMetadataOperand<'a>(M: &'a Module, Name: *const c_char, Val: &'a Value); // Operations on scalar constants pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; @@ -1037,14 +1083,14 @@ Length: c_uint, DontNullTerminate: Bool, ) -> &Value; - pub fn LLVMConstStructInContext( + pub fn LLVMConstStructInContext<'a>( C: &'a Context, ConstantVals: *const &'a Value, Count: c_uint, Packed: Bool, ) -> &'a Value; - pub fn LLVMConstArray( + pub fn LLVMConstArray<'a>( ElementTy: &'a Type, ConstantVals: *const &'a Value, Length: c_uint, @@ -1052,17 +1098,17 @@ pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions - pub fn LLVMRustConstInBoundsGEP2( + pub fn LLVMRustConstInBoundsGEP2<'a>( ty: &'a Type, ConstantVal: &'a Value, ConstantIndices: *const &'a Value, NumIndices: c_uint, ) -> &'a Value; - pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstZExt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstExtractValue( AggConstant: &Value, IdxList: *const c_uint, @@ -1083,20 +1129,20 @@ // Operations on global variables pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; - pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; - pub fn LLVMRustGetOrInsertGlobal( + pub fn LLVMRustGetOrInsertGlobal<'a>( M: &'a Module, Name: *const c_char, NameLen: size_t, T: &'a Type, ) -> &'a Value; - pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value; + pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value; pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMDeleteGlobal(GlobalVar: &Value); pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>; - pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value); + pub fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value); pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool; pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool); pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); @@ -1110,7 +1156,7 @@ pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); // Operations on functions - pub fn LLVMRustGetOrInsertFunction( + pub fn LLVMRustGetOrInsertFunction<'a>( M: &'a Module, Name: *const c_char, NameLen: size_t, @@ -1138,7 +1184,7 @@ // Operations on basic blocks pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value; - pub fn LLVMAppendBasicBlockInContext( + pub fn LLVMAppendBasicBlockInContext<'a>( C: &'a Context, Fn: &'a Value, Name: *const c_char, @@ -1162,7 +1208,7 @@ pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); // Operations on phi nodes - pub fn LLVMAddIncoming( + pub fn LLVMAddIncoming<'a>( PhiNode: &'a Value, IncomingValues: *const &'a Value, IncomingBlocks: *const &'a BasicBlock, @@ -1170,31 +1216,31 @@ ); // Instruction builders - pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>; - pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock); - pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock; - pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>); + pub fn LLVMCreateBuilderInContext(C: &Context) -> &mut Builder<'_>; + pub fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock); + pub fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock; + pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); // Metadata - pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: &'a Value); + pub fn LLVMSetCurrentDebugLocation<'a>(Builder: &Builder<'a>, L: &'a Value); // Terminators - pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value; - pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value; - pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; - pub fn LLVMBuildCondBr( + pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value; + pub fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; + pub fn LLVMBuildCondBr<'a>( B: &Builder<'a>, If: &'a Value, Then: &'a BasicBlock, Else: &'a BasicBlock, ) -> &'a Value; - pub fn LLVMBuildSwitch( + pub fn LLVMBuildSwitch<'a>( B: &Builder<'a>, V: &'a Value, Else: &'a BasicBlock, NumCases: c_uint, ) -> &'a Value; - pub fn LLVMRustBuildInvoke( + pub fn LLVMRustBuildInvoke<'a>( B: &Builder<'a>, Ty: &'a Type, Fn: &'a Value, @@ -1205,239 +1251,239 @@ Bundle: Option<&OperandBundleDef<'a>>, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLandingPad( + pub fn LLVMBuildLandingPad<'a>( B: &Builder<'a>, Ty: &'a Type, PersFn: Option<&'a Value>, NumClauses: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; - pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; + pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value; - pub fn LLVMRustBuildCleanupPad( + pub fn LLVMRustBuildCleanupPad<'a>( B: &Builder<'a>, ParentPad: Option<&'a Value>, ArgCnt: c_uint, Args: *const &'a Value, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCleanupRet( + pub fn LLVMRustBuildCleanupRet<'a>( B: &Builder<'a>, CleanupPad: &'a Value, UnwindBB: Option<&'a BasicBlock>, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchPad( + pub fn LLVMRustBuildCatchPad<'a>( B: &Builder<'a>, ParentPad: &'a Value, ArgCnt: c_uint, Args: *const &'a Value, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchRet( + pub fn LLVMRustBuildCatchRet<'a>( B: &Builder<'a>, Pad: &'a Value, BB: &'a BasicBlock, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchSwitch( + pub fn LLVMRustBuildCatchSwitch<'a>( Builder: &Builder<'a>, ParentPad: Option<&'a Value>, BB: Option<&'a BasicBlock>, NumHandlers: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock); - pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value); + pub fn LLVMRustAddHandler<'a>(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value); // Add a case to the switch instruction - pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); + pub fn LLVMAddCase<'a>(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); // Add a clause to the landing pad instruction - pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value); + pub fn LLVMAddClause<'a>(LandingPad: &'a Value, ClauseVal: &'a Value); // Set the cleanup on a landing pad instruction pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool); // Arithmetic - pub fn LLVMBuildAdd( + pub fn LLVMBuildAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFAdd( + pub fn LLVMBuildFAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSub( + pub fn LLVMBuildSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFSub( + pub fn LLVMBuildFSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildMul( + pub fn LLVMBuildMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFMul( + pub fn LLVMBuildFMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildUDiv( + pub fn LLVMBuildUDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExactUDiv( + pub fn LLVMBuildExactUDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSDiv( + pub fn LLVMBuildSDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExactSDiv( + pub fn LLVMBuildExactSDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFDiv( + pub fn LLVMBuildFDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildURem( + pub fn LLVMBuildURem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSRem( + pub fn LLVMBuildSRem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFRem( + pub fn LLVMBuildFRem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildShl( + pub fn LLVMBuildShl<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLShr( + pub fn LLVMBuildLShr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildAShr( + pub fn LLVMBuildAShr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWAdd( + pub fn LLVMBuildNSWAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWAdd( + pub fn LLVMBuildNUWAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWSub( + pub fn LLVMBuildNSWSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWSub( + pub fn LLVMBuildNUWSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWMul( + pub fn LLVMBuildNSWMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWMul( + pub fn LLVMBuildNUWMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildAnd( + pub fn LLVMBuildAnd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildOr( + pub fn LLVMBuildOr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildXor( + pub fn LLVMBuildXor<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMRustSetFastMath(Instr: &Value); // Memory - pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildArrayAlloca( + pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildArrayAlloca<'a>( B: &Builder<'a>, Ty: &'a Type, Val: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLoad2( + pub fn LLVMBuildLoad2<'a>( B: &Builder<'a>, Ty: &'a Type, PointerVal: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; + pub fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; - pub fn LLVMBuildGEP2( + pub fn LLVMBuildGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1445,7 +1491,7 @@ NumIndices: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInBoundsGEP2( + pub fn LLVMBuildInBoundsGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1453,7 +1499,7 @@ NumIndices: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildStructGEP2( + pub fn LLVMBuildStructGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1462,85 +1508,85 @@ ) -> &'a Value; // Casts - pub fn LLVMBuildTrunc( + pub fn LLVMBuildTrunc<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildZExt( + pub fn LLVMBuildZExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSExt( + pub fn LLVMBuildSExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPToUI( + pub fn LLVMBuildFPToUI<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPToSI( + pub fn LLVMBuildFPToSI<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildUIToFP( + pub fn LLVMBuildUIToFP<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSIToFP( + pub fn LLVMBuildSIToFP<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPTrunc( + pub fn LLVMBuildFPTrunc<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPExt( + pub fn LLVMBuildFPExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildPtrToInt( + pub fn LLVMBuildPtrToInt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildIntToPtr( + pub fn LLVMBuildIntToPtr<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildBitCast( + pub fn LLVMBuildBitCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildPointerCast( + pub fn LLVMBuildPointerCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildIntCast( + pub fn LLVMRustBuildIntCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, @@ -1548,14 +1594,14 @@ ) -> &'a Value; // Comparisons - pub fn LLVMBuildICmp( + pub fn LLVMBuildICmp<'a>( B: &Builder<'a>, Op: c_uint, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFCmp( + pub fn LLVMBuildFCmp<'a>( B: &Builder<'a>, Op: c_uint, LHS: &'a Value, @@ -1564,9 +1610,9 @@ ) -> &'a Value; // Miscellaneous instructions - pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &'a Value; - pub fn LLVMRustBuildCall( + pub fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value; + pub fn LLVMRustBuildCall<'a>( B: &Builder<'a>, Ty: &'a Type, Fn: &'a Value, @@ -1574,7 +1620,7 @@ NumArgs: c_uint, Bundle: Option<&OperandBundleDef<'a>>, ) -> &'a Value; - pub fn LLVMRustBuildMemCpy( + pub fn LLVMRustBuildMemCpy<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1583,7 +1629,7 @@ Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMRustBuildMemMove( + pub fn LLVMRustBuildMemMove<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1592,7 +1638,7 @@ Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMRustBuildMemSet( + pub fn LLVMRustBuildMemSet<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1600,46 +1646,46 @@ Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMBuildSelect( + pub fn LLVMBuildSelect<'a>( B: &Builder<'a>, If: &'a Value, Then: &'a Value, Else: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildVAArg( + pub fn LLVMBuildVAArg<'a>( B: &Builder<'a>, list: &'a Value, Ty: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExtractElement( + pub fn LLVMBuildExtractElement<'a>( B: &Builder<'a>, VecVal: &'a Value, Index: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInsertElement( + pub fn LLVMBuildInsertElement<'a>( B: &Builder<'a>, VecVal: &'a Value, EltVal: &'a Value, Index: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildShuffleVector( + pub fn LLVMBuildShuffleVector<'a>( B: &Builder<'a>, V1: &'a Value, V2: &'a Value, Mask: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExtractValue( + pub fn LLVMBuildExtractValue<'a>( B: &Builder<'a>, AggVal: &'a Value, Index: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInsertValue( + pub fn LLVMBuildInsertValue<'a>( B: &Builder<'a>, AggVal: &'a Value, EltVal: &'a Value, @@ -1647,41 +1693,47 @@ Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFAdd( + pub fn LLVMRustBuildVectorReduceFAdd<'a>( B: &Builder<'a>, Acc: &'a Value, Src: &'a Value, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMul( + pub fn LLVMRustBuildVectorReduceFMul<'a>( B: &Builder<'a>, Acc: &'a Value, Src: &'a Value, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMin( + pub fn LLVMRustBuildVectorReduceAdd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceMul<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceAnd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceOr<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceXor<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceMin<'a>( B: &Builder<'a>, Src: &'a Value, IsSigned: bool, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMax( + pub fn LLVMRustBuildVectorReduceMax<'a>( B: &Builder<'a>, Src: &'a Value, IsSigned: bool, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>, Src: &'a Value, IsNaN: bool) - -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>, Src: &'a Value, IsNaN: bool) - -> &'a Value; + pub fn LLVMRustBuildVectorReduceFMin<'a>( + B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool, + ) -> &'a Value; + pub fn LLVMRustBuildVectorReduceFMax<'a>( + B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool, + ) -> &'a Value; - pub fn LLVMRustBuildMinNum(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; - pub fn LLVMRustBuildMaxNum(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; + pub fn LLVMRustBuildMinNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; + pub fn LLVMRustBuildMaxNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; // Atomic Operations - pub fn LLVMRustBuildAtomicLoad( + pub fn LLVMRustBuildAtomicLoad<'a>( B: &Builder<'a>, ElementType: &'a Type, PointerVal: &'a Value, @@ -1689,14 +1741,14 @@ Order: AtomicOrdering, ) -> &'a Value; - pub fn LLVMRustBuildAtomicStore( + pub fn LLVMRustBuildAtomicStore<'a>( B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value, Order: AtomicOrdering, ) -> &'a Value; - pub fn LLVMRustBuildAtomicCmpXchg( + pub fn LLVMRustBuildAtomicCmpXchg<'a>( B: &Builder<'a>, LHS: &'a Value, CMP: &'a Value, @@ -1706,7 +1758,7 @@ Weak: Bool, ) -> &'a Value; - pub fn LLVMBuildAtomicRMW( + pub fn LLVMBuildAtomicRMW<'a>( B: &Builder<'a>, Op: AtomicRmwBinOp, LHS: &'a Value, @@ -1725,16 +1777,16 @@ pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; /// Creates a pass manager. - pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>; + pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>; + pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> &mut PassManager<'_>; /// Disposes a pass manager. - pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>); + pub fn LLVMDisposePassManager<'a>(PM: &'a mut PassManager<'a>); /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool; + pub fn LLVMRunPassManager<'a>(PM: &PassManager<'a>, M: &'a Module) -> Bool; pub fn LLVMInitializePasses(); @@ -1744,7 +1796,7 @@ pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char); - pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>); + pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); @@ -1788,7 +1840,7 @@ pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; - pub fn LLVMStructSetBody( + pub fn LLVMStructSetBody<'a>( StructTy: &'a Type, ElementTypes: *const &'a Type, ElementCount: c_uint, @@ -1805,6 +1857,7 @@ SideEffects: Bool, AlignStack: Bool, Dialect: AsmDialect, + CanThrow: Bool, ) -> &Value; pub fn LLVMRustInlineAsmVerify( Ty: &Type, @@ -1830,8 +1883,7 @@ BufferOut: &RustString, ); - pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char) - -> &'a Value; + pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &Value, FuncName: *const c_char) -> &Value; pub fn LLVMRustCoverageHashCString(StrVal: *const c_char) -> u64; pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64; @@ -1850,17 +1902,19 @@ pub fn LLVMRustVersionMinor() -> u32; pub fn LLVMRustVersionPatch() -> u32; + pub fn LLVMRustIsRustLLVM() -> bool; + pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32); - pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value; + pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; - pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>; + pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>; - pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>); + pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>); pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder<'_>); - pub fn LLVMRustDIBuilderCreateCompileUnit( + pub fn LLVMRustDIBuilderCreateCompileUnit<'a>( Builder: &DIBuilder<'a>, Lang: c_uint, File: &'a DIFile, @@ -1876,7 +1930,7 @@ SplitDebugInlining: bool, ) -> &'a DIDescriptor; - pub fn LLVMRustDIBuilderCreateFile( + pub fn LLVMRustDIBuilderCreateFile<'a>( Builder: &DIBuilder<'a>, Filename: *const c_char, FilenameLen: size_t, @@ -1887,12 +1941,12 @@ ChecksumLen: size_t, ) -> &'a DIFile; - pub fn LLVMRustDIBuilderCreateSubroutineType( + pub fn LLVMRustDIBuilderCreateSubroutineType<'a>( Builder: &DIBuilder<'a>, ParameterTypes: &'a DIArray, ) -> &'a DICompositeType; - pub fn LLVMRustDIBuilderCreateFunction( + pub fn LLVMRustDIBuilderCreateFunction<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, @@ -1910,7 +1964,7 @@ Decl: Option<&'a DIDescriptor>, ) -> &'a DISubprogram; - pub fn LLVMRustDIBuilderCreateBasicType( + pub fn LLVMRustDIBuilderCreateBasicType<'a>( Builder: &DIBuilder<'a>, Name: *const c_char, NameLen: size_t, @@ -1918,7 +1972,7 @@ Encoding: c_uint, ) -> &'a DIBasicType; - pub fn LLVMRustDIBuilderCreateTypedef( + pub fn LLVMRustDIBuilderCreateTypedef<'a>( Builder: &DIBuilder<'a>, Type: &'a DIBasicType, Name: *const c_char, @@ -1928,7 +1982,7 @@ Scope: Option<&'a DIScope>, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreatePointerType( + pub fn LLVMRustDIBuilderCreatePointerType<'a>( Builder: &DIBuilder<'a>, PointeeTy: &'a DIType, SizeInBits: u64, @@ -1938,7 +1992,7 @@ NameLen: size_t, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreateStructType( + pub fn LLVMRustDIBuilderCreateStructType<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIDescriptor>, Name: *const c_char, @@ -1956,7 +2010,7 @@ UniqueIdLen: size_t, ) -> &'a DICompositeType; - pub fn LLVMRustDIBuilderCreateMemberType( + pub fn LLVMRustDIBuilderCreateMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, @@ -1970,7 +2024,7 @@ Ty: &'a DIType, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreateVariantMemberType( + pub fn LLVMRustDIBuilderCreateVariantMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -1985,7 +2039,7 @@ Ty: &'a DIType, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateLexicalBlock( + pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, File: &'a DIFile, @@ -1993,13 +2047,13 @@ Col: c_uint, ) -> &'a DILexicalBlock; - pub fn LLVMRustDIBuilderCreateLexicalBlockFile( + pub fn LLVMRustDIBuilderCreateLexicalBlockFile<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, File: &'a DIFile, ) -> &'a DILexicalBlock; - pub fn LLVMRustDIBuilderCreateStaticVariable( + pub fn LLVMRustDIBuilderCreateStaticVariable<'a>( Builder: &DIBuilder<'a>, Context: Option<&'a DIScope>, Name: *const c_char, @@ -2015,7 +2069,7 @@ AlignInBits: u32, ) -> &'a DIGlobalVariableExpression; - pub fn LLVMRustDIBuilderCreateVariable( + pub fn LLVMRustDIBuilderCreateVariable<'a>( Builder: &DIBuilder<'a>, Tag: c_uint, Scope: &'a DIDescriptor, @@ -2030,7 +2084,7 @@ AlignInBits: u32, ) -> &'a DIVariable; - pub fn LLVMRustDIBuilderCreateArrayType( + pub fn LLVMRustDIBuilderCreateArrayType<'a>( Builder: &DIBuilder<'a>, Size: u64, AlignInBits: u32, @@ -2038,29 +2092,29 @@ Subscripts: &'a DIArray, ) -> &'a DIType; - pub fn LLVMRustDIBuilderGetOrCreateSubrange( + pub fn LLVMRustDIBuilderGetOrCreateSubrange<'a>( Builder: &DIBuilder<'a>, Lo: i64, Count: i64, ) -> &'a DISubrange; - pub fn LLVMRustDIBuilderGetOrCreateArray( + pub fn LLVMRustDIBuilderGetOrCreateArray<'a>( Builder: &DIBuilder<'a>, Ptr: *const Option<&'a DIDescriptor>, Count: c_uint, ) -> &'a DIArray; - pub fn LLVMRustDIBuilderInsertDeclareAtEnd( + pub fn LLVMRustDIBuilderInsertDeclareAtEnd<'a>( Builder: &DIBuilder<'a>, Val: &'a Value, VarInfo: &'a DIVariable, - AddrOps: *const i64, + AddrOps: *const u64, AddrOpsCount: c_uint, DL: &'a DILocation, InsertAtEnd: &'a BasicBlock, ) -> &'a Value; - pub fn LLVMRustDIBuilderCreateEnumerator( + pub fn LLVMRustDIBuilderCreateEnumerator<'a>( Builder: &DIBuilder<'a>, Name: *const c_char, NameLen: size_t, @@ -2068,7 +2122,7 @@ IsUnsigned: bool, ) -> &'a DIEnumerator; - pub fn LLVMRustDIBuilderCreateEnumerationType( + pub fn LLVMRustDIBuilderCreateEnumerationType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -2082,7 +2136,7 @@ IsScoped: bool, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateUnionType( + pub fn LLVMRustDIBuilderCreateUnionType<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2098,7 +2152,7 @@ UniqueIdLen: size_t, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateVariantPart( + pub fn LLVMRustDIBuilderCreateVariantPart<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -2116,7 +2170,7 @@ pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); - pub fn LLVMRustDIBuilderCreateTemplateTypeParameter( + pub fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2124,7 +2178,7 @@ Ty: &'a DIType, ) -> &'a DITemplateTypeParameter; - pub fn LLVMRustDIBuilderCreateNameSpace( + pub fn LLVMRustDIBuilderCreateNameSpace<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2132,21 +2186,21 @@ ExportSymbols: bool, ) -> &'a DINameSpace; - pub fn LLVMRustDICompositeTypeReplaceArrays( + pub fn LLVMRustDICompositeTypeReplaceArrays<'a>( Builder: &DIBuilder<'a>, CompositeType: &'a DIType, Elements: Option<&'a DIArray>, Params: Option<&'a DIArray>, ); - pub fn LLVMRustDIBuilderCreateDebugLocation( + pub fn LLVMRustDIBuilderCreateDebugLocation<'a>( Line: c_uint, Column: c_uint, Scope: &'a DIScope, InlinedAt: Option<&'a DILocation>, ) -> &'a DILocation; - pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; - pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; + pub fn LLVMRustDIBuilderCreateOpDeref() -> u64; + pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64; #[allow(improper_ctypes)] pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); @@ -2205,7 +2259,7 @@ SplitDwarfFile: *const c_char, ) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddBuilderLibraryInfo( + pub fn LLVMRustAddBuilderLibraryInfo<'a>( PMB: &'a PassManagerBuilder, M: &'a Module, DisableSimplifyLibCalls: bool, @@ -2221,13 +2275,13 @@ PGOUsePath: *const c_char, PGOSampleUsePath: *const c_char, ); - pub fn LLVMRustAddLibraryInfo( + pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, M: &'a Module, DisableSimplifyLibCalls: bool, ); - pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module); - pub fn LLVMRustWriteOutputFile( + pub fn LLVMRustRunFunctionPassManager<'a>(PM: &PassManager<'a>, M: &'a Module); + pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module, @@ -2235,7 +2289,7 @@ DwoOutput: *const c_char, FileType: FileType, ) -> LLVMRustResult; - pub fn LLVMRustOptimizeWithNewPassManager( + pub fn LLVMRustOptimizeWithNewPassManager<'a>( M: &'a Module, TM: &'a TargetMachine, OptLevel: PassBuilderOptLevel, @@ -2261,9 +2315,11 @@ end_callback: SelfProfileAfterPassCallback, ExtraPasses: *const c_char, ExtraPassesLen: size_t, + LLVMPlugins: *const c_char, + LLVMPluginsLen: size_t, ) -> LLVMRustResult; pub fn LLVMRustPrintModule( - M: &'a Module, + M: &Module, Output: *const c_char, Demangle: extern "C" fn(*const c_char, size_t, *mut c_char, size_t) -> size_t, ) -> LLVMRustResult; @@ -2276,27 +2332,21 @@ pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; - pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>; - pub fn LLVMRustArchiveIteratorNext( + pub fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>; + pub fn LLVMRustArchiveIteratorNext<'a>( AIR: &ArchiveIterator<'a>, ) -> Option<&'a mut ArchiveChild<'a>>; pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>); - pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>); + pub fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>); + pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); - pub fn LLVMContextSetDiagnosticHandler( - C: &Context, - Handler: DiagnosticHandler, - DiagnosticContext: *mut c_void, - ); - #[allow(improper_ctypes)] - pub fn LLVMRustUnpackOptimizationDiagnostic( + pub fn LLVMRustUnpackOptimizationDiagnostic<'a>( DI: &'a DiagnosticInfo, pass_name_out: &RustString, function_out: &mut Option<&'a Value>, @@ -2306,7 +2356,7 @@ message_out: &RustString, ); - pub fn LLVMRustUnpackInlineAsmDiagnostic( + pub fn LLVMRustUnpackInlineAsmDiagnostic<'a>( DI: &'a DiagnosticInfo, level_out: &mut DiagnosticLevel, cookie_out: &mut c_uint, @@ -2317,14 +2367,14 @@ pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; - pub fn LLVMRustGetSMDiagnostic( + pub fn LLVMRustGetSMDiagnostic<'a>( DI: &'a DiagnosticInfo, cookie_out: &mut c_uint, ) -> &'a SMDiagnostic; pub fn LLVMRustSetInlineAsmDiagnosticHandler( C: &Context, - H: InlineAsmDiagHandler, + H: InlineAsmDiagHandlerTy, CX: *mut c_void, ); @@ -2346,12 +2396,12 @@ WriteSymbtab: bool, Kind: ArchiveKind, ) -> LLVMRustResult; - pub fn LLVMRustArchiveMemberNew( + pub fn LLVMRustArchiveMemberNew<'a>( Filename: *const c_char, Name: *const c_char, Child: Option<&ArchiveChild<'a>>, ) -> &'a mut RustArchiveMember<'a>; - pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>); + pub fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>); pub fn LLVMRustWriteImportLibrary( ImportName: *const c_char, @@ -2362,18 +2412,18 @@ MinGW: bool, ) -> LLVMRustResult; - pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine); + pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine); - pub fn LLVMRustBuildOperandBundleDef( + pub fn LLVMRustBuildOperandBundleDef<'a>( Name: *const c_char, Inputs: *const &'a Value, NumInputs: c_uint, ) -> &'a mut OperandBundleDef<'a>; - pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>); + pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>); - pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); + pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); - pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); + pub fn LLVMRustSetComdat<'a>(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); pub fn LLVMRustUnsetComdat(V: &Value); pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); @@ -2426,17 +2476,32 @@ pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); - pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; + pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub fn LLVMRustLinkerAdd( linker: &Linker<'_>, bytecode: *const c_char, bytecode_len: usize, ) -> bool; - pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>); + pub fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>); #[allow(improper_ctypes)] pub fn LLVMRustComputeLTOCacheKey( key_out: &RustString, mod_id: *const c_char, data: &ThinLTOData, ); + + pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>; + pub fn LLVMRustContextSetDiagnosticHandler( + context: &Context, + diagnostic_handler: Option<&DiagnosticHandler>, + ); + pub fn LLVMRustContextConfigureDiagnosticHandler( + context: &Context, + diagnostic_handler_callback: DiagnosticHandlerTy, + diagnostic_handler_context: *mut c_void, + remark_all_passes: bool, + remark_passes: *const *const c_char, + remark_passes_len: usize, + ); + } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,13 +31,13 @@ } } -pub fn AddFunctionAttrStringValue(llfn: &'a Value, idx: AttributePlace, attr: &CStr, value: &CStr) { +pub fn AddFunctionAttrStringValue(llfn: &Value, idx: AttributePlace, attr: &CStr, value: &CStr) { unsafe { LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), value.as_ptr()) } } -pub fn AddFunctionAttrString(llfn: &'a Value, idx: AttributePlace, attr: &CStr) { +pub fn AddFunctionAttrString(llfn: &Value, idx: AttributePlace, attr: &CStr) { unsafe { LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), std::ptr::null()) } @@ -86,12 +86,12 @@ } } -pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { +pub fn SetInstructionCallConv(instr: &Value, cc: CallConv) { unsafe { LLVMSetInstructionCallConv(instr, cc as c_uint); } } -pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { +pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) { unsafe { LLVMSetFunctionCallConv(fn_, cc as c_uint); } @@ -103,26 +103,26 @@ // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the // function. // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 -pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { +pub fn SetUniqueComdat(llmod: &Module, val: &Value) { unsafe { let name = get_value_name(val); LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); } } -pub fn UnsetComdat(val: &'a Value) { +pub fn UnsetComdat(val: &Value) { unsafe { LLVMRustUnsetComdat(val); } } -pub fn SetUnnamedAddress(global: &'a Value, unnamed: UnnamedAddr) { +pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { unsafe { LLVMSetUnnamedAddress(global, unnamed); } } -pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) { +pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) { unsafe { LLVMSetThreadLocalMode(global, mode); } @@ -264,7 +264,7 @@ pub raw: &'a mut ffi::OperandBundleDef<'a>, } -impl OperandBundleDef<'a> { +impl<'a> OperandBundleDef<'a> { pub fn new(name: &str, vals: &[&'a Value]) -> Self { let name = SmallCStr::new(name); let def = unsafe { @@ -274,7 +274,7 @@ } } -impl Drop for OperandBundleDef<'a> { +impl Drop for OperandBundleDef<'_> { fn drop(&mut self) { unsafe { LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,9 +1,10 @@ use crate::back::write::create_informational_target_machine; use crate::{llvm, llvm_util}; use libc::c_int; +use libloading::Library; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; -use rustc_metadata::dynamic_lib::DynamicLibrary; +use rustc_fs_util::path_to_c_string; use rustc_middle::bug; use rustc_session::config::PrintRequest; use rustc_session::Session; @@ -120,14 +121,20 @@ llvm::LLVMInitializePasses(); - for plugin in &sess.opts.debugging_opts.llvm_plugins { - let path = Path::new(plugin); - let res = DynamicLibrary::open(path); - match res { - Ok(_) => debug!("LLVM plugin loaded succesfully {} ({})", path.display(), plugin), - Err(e) => bug!("couldn't load plugin: {}", e), + // Use the legacy plugin registration if we don't use the new pass manager + if !should_use_new_llvm_pass_manager( + &sess.opts.debugging_opts.new_llvm_pass_manager, + &sess.target.arch, + ) { + // Register LLVM plugins by loading them into the compiler process. + for plugin in &sess.opts.debugging_opts.llvm_plugins { + let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e)); + debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + mem::forget(lib); } - mem::forget(res); } rustc_llvm::initialize_available_targets(); @@ -135,9 +142,9 @@ llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); } -pub fn time_trace_profiler_finish(file_name: &str) { +pub fn time_trace_profiler_finish(file_name: &Path) { unsafe { - let file_name = CString::new(file_name).unwrap(); + let file_name = path_to_c_string(file_name); llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr()); } } @@ -216,6 +223,12 @@ } } +/// Returns `true` if this LLVM is Rust's bundled LLVM (and not system LLVM). +pub fn is_rust_llvm() -> bool { + // Can be called without initializing LLVM + unsafe { llvm::LLVMRustIsRustLLVM() } +} + pub fn print_passes() { // Can be called without initializing LLVM unsafe { @@ -410,3 +423,13 @@ let name = sess.opts.debugging_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } + +pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option, target_arch: &str) -> bool { + // The new pass manager is enabled by default for LLVM >= 13. + // This matches Clang, which also enables it since Clang 13. + + // FIXME: There are some perf issues with the new pass manager + // when targeting s390x, so it is temporarily disabled for that + // arch, see https://github.com/rust-lang/rust/issues/89609 + user_opt.unwrap_or_else(|| target_arch != "s390x" && llvm_util::get_version() >= (13, 0, 0)) +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/mono_item.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/mono_item.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/mono_item.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/mono_item.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,7 +13,7 @@ use rustc_target::spec::RelocModel; use tracing::debug; -impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { fn predefine_static( &self, def_id: DefId, @@ -92,7 +92,7 @@ } } -impl CodegenCx<'ll, 'tcx> { +impl CodegenCx<'_, '_> { /// Whether a definition or declaration can be assumed to be local to a group of /// libraries that form a single DSO or executable. pub(crate) unsafe fn should_assume_dso_local( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/type_.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/type_.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/type_.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/type_.rs 2022-02-23 04:07:21.000000000 +0000 @@ -38,7 +38,7 @@ } } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { crate fn type_named_struct(&self, name: &str) -> &'ll Type { let name = SmallCStr::new(name); unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) } @@ -133,7 +133,7 @@ } } -impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn type_i1(&self) -> &'ll Type { unsafe { llvm::LLVMInt1TypeInContext(self.llcx) } } @@ -252,7 +252,7 @@ } } -impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { layout.llvm_type(self) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/va_arg.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/va_arg.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/va_arg.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_llvm/src/va_arg.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,8 +11,8 @@ use rustc_middle::ty::Ty; use rustc_target::abi::{Align, Endian, HasDataLayout, Size}; -fn round_pointer_up_to_alignment( - bx: &mut Builder<'a, 'll, 'tcx>, +fn round_pointer_up_to_alignment<'ll>( + bx: &mut Builder<'_, 'll, '_>, addr: &'ll Value, align: Align, ptr_ty: &'ll Type, @@ -23,8 +23,8 @@ bx.inttoptr(ptr_as_int, ptr_ty) } -fn emit_direct_ptr_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_direct_ptr_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, llty: &'ll Type, size: Size, @@ -62,8 +62,8 @@ } } -fn emit_ptr_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_ptr_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, indirect: bool, @@ -90,8 +90,8 @@ } } -fn emit_aapcs_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_aapcs_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, ) -> &'ll Value { @@ -175,8 +175,8 @@ val } -pub(super) fn emit_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +pub(super) fn emit_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, ) -> &'ll Value { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -14,11 +14,14 @@ libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" +thorin-dwp = "0.1.1" pathdiff = "0.2.0" +snap = "1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } regex = "1.4" rustc_serialize = { path = "../rustc_serialize" } +rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/command.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/command.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/command.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/command.rs 2022-02-23 04:07:21.000000000 +0000 @@ -48,7 +48,7 @@ } pub fn sym_arg(&mut self, arg: Symbol) -> &mut Command { - self.arg(&*arg.as_str()); + self.arg(arg.as_str()); self } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/link.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/link.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/link.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/link.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,11 +1,13 @@ +use rustc_arena::TypedArena; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; -use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; +use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind}; use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; @@ -14,7 +16,6 @@ /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_target::abi::Endian; use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; @@ -22,6 +23,7 @@ use super::archive::{find_library, ArchiveBuilder}; use super::command::Command; use super::linker::{self, Linker}; +use super::metadata::create_rmeta_file; use super::rpath::{self, RPathConfig}; use crate::{ looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, @@ -29,13 +31,13 @@ }; use cc::windows_registry; -use object::elf; -use object::write::Object; -use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind}; use regex::Regex; use tempfile::Builder as TempFileBuilder; +use std::borrow::Borrow; use std::ffi::OsString; +use std::fs::{File, OpenOptions}; +use std::io::{BufWriter, Write}; use std::lazy::OnceCell; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; @@ -91,7 +93,7 @@ sess, crate_type, outputs, - &codegen_results.crate_info.local_crate_name.as_str(), + codegen_results.crate_info.local_crate_name.as_str(), ); match crate_type { CrateType::Rlib => { @@ -137,31 +139,47 @@ } } - // Remove the temporary object file and metadata if we aren't saving temps + // Remove the temporary object file and metadata if we aren't saving temps. sess.time("link_binary_remove_temps", || { - if !sess.opts.cg.save_temps { - let remove_temps_from_module = |module: &CompiledModule| { - if let Some(ref obj) = module.object { - ensure_removed(sess.diagnostic(), obj); - } - - if let Some(ref obj) = module.dwarf_object { - ensure_removed(sess.diagnostic(), obj); - } - }; + // If the user requests that temporaries are saved, don't delete any. + if sess.opts.cg.save_temps { + return; + } - if sess.opts.output_types.should_link() && !preserve_objects_for_their_debuginfo(sess) { - for module in &codegen_results.modules { - remove_temps_from_module(module); - } + let remove_temps_from_module = |module: &CompiledModule| { + if let Some(ref obj) = module.object { + ensure_removed(sess.diagnostic(), obj); } + }; - if let Some(ref metadata_module) = codegen_results.metadata_module { - remove_temps_from_module(metadata_module); + // Otherwise, always remove the metadata and allocator module temporaries. + if let Some(ref metadata_module) = codegen_results.metadata_module { + remove_temps_from_module(metadata_module); + } + + if let Some(ref allocator_module) = codegen_results.allocator_module { + remove_temps_from_module(allocator_module); + } + + // If no requested outputs require linking, then the object temporaries should + // be kept. + if !sess.opts.output_types.should_link() { + return; + } + + // Potentially keep objects for their debuginfo. + let (preserve_objects, preserve_dwarf_objects) = preserve_objects_for_their_debuginfo(sess); + debug!(?preserve_objects, ?preserve_dwarf_objects); + + for module in &codegen_results.modules { + if !preserve_objects { + remove_temps_from_module(module); } - if let Some(ref allocator_module) = codegen_results.allocator_module { - remove_temps_from_module(allocator_module); + if !preserve_dwarf_objects { + if let Some(ref obj) = module.dwarf_object { + ensure_removed(sess.diagnostic(), obj); + } } } }); @@ -248,8 +266,14 @@ let mut ab = ::new(sess, out_filename, None); - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - ab.add_file(obj); + for m in &codegen_results.modules { + if let Some(obj) = m.object.as_ref() { + ab.add_file(obj); + } + + if let Some(dwarf_obj) = m.dwarf_object.as_ref() { + ab.add_file(dwarf_obj); + } } // Note that in this loop we are ignoring the value of `lib.cfg`. That is, @@ -339,7 +363,7 @@ // metadata in rlib files is wrapped in a "dummy" object file for // the target platform so the rlib can be processed entirely by // normal linkers for the platform. - let metadata = create_metadata_file(sess, codegen_results.metadata.raw_data()); + let metadata = create_rmeta_file(sess, codegen_results.metadata.raw_data()); ab.add_file(&emit_metadata(sess, &metadata, tmpdir)); // After adding all files to the archive, we need to update the @@ -358,136 +382,6 @@ } } return Ok(ab); - - // For rlibs we "pack" rustc metadata into a dummy object file. When rustc - // creates a dylib crate type it will pass `--whole-archive` (or the - // platform equivalent) to include all object files from an rlib into the - // final dylib itself. This causes linkers to iterate and try to include all - // files located in an archive, so if metadata is stored in an archive then - // it needs to be of a form that the linker will be able to process. - // - // Note, though, that we don't actually want this metadata to show up in any - // final output of the compiler. Instead this is purely for rustc's own - // metadata tracking purposes. - // - // With the above in mind, each "flavor" of object format gets special - // handling here depending on the target: - // - // * MachO - macos-like targets will insert the metadata into a section that - // is sort of fake dwarf debug info. Inspecting the source of the macos - // linker this causes these sections to be skipped automatically because - // it's not in an allowlist of otherwise well known dwarf section names to - // go into the final artifact. - // - // * WebAssembly - we actually don't have any container format for this - // target. WebAssembly doesn't support the `dylib` crate type anyway so - // there's no need for us to support this at this time. Consequently the - // metadata bytes are simply stored as-is into an rlib. - // - // * COFF - Windows-like targets create an object with a section that has - // the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker - // ever sees the section it doesn't process it and it's removed. - // - // * ELF - All other targets are similar to Windows in that there's a - // `SHF_EXCLUDE` flag we can set on sections in an object file to get - // automatically removed from the final output. - // - // Note that this metdata format is kept in sync with - // `rustc_codegen_ssa/src/back/metadata.rs`. - fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec { - let endianness = match sess.target.options.endian { - Endian::Little => Endianness::Little, - Endian::Big => Endianness::Big, - }; - let architecture = match &sess.target.arch[..] { - "arm" => Architecture::Arm, - "aarch64" => Architecture::Aarch64, - "x86" => Architecture::I386, - "s390x" => Architecture::S390x, - "mips" => Architecture::Mips, - "mips64" => Architecture::Mips64, - "x86_64" => { - if sess.target.pointer_width == 32 { - Architecture::X86_64_X32 - } else { - Architecture::X86_64 - } - } - "powerpc" => Architecture::PowerPc, - "powerpc64" => Architecture::PowerPc64, - "riscv32" => Architecture::Riscv32, - "riscv64" => Architecture::Riscv64, - "sparc64" => Architecture::Sparc64, - - // This is used to handle all "other" targets. This includes targets - // in two categories: - // - // * Some targets don't have support in the `object` crate just yet - // to write an object file. These targets are likely to get filled - // out over time. - // - // * Targets like WebAssembly don't support dylibs, so the purpose - // of putting metadata in object files, to support linking rlibs - // into dylibs, is moot. - // - // In both of these cases it means that linking into dylibs will - // not be supported by rustc. This doesn't matter for targets like - // WebAssembly and for targets not supported by the `object` crate - // yet it means that work will need to be done in the `object` crate - // to add a case above. - _ => return metadata.to_vec(), - }; - - if sess.target.is_like_osx { - let mut file = Object::new(BinaryFormat::MachO, architecture, endianness); - - let section = - file.add_section(b"__DWARF".to_vec(), b".rmeta".to_vec(), SectionKind::Debug); - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } else if sess.target.is_like_windows { - const IMAGE_SCN_LNK_REMOVE: u32 = 0; - let mut file = Object::new(BinaryFormat::Coff, architecture, endianness); - - let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug); - file.section_mut(section).flags = - SectionFlags::Coff { characteristics: IMAGE_SCN_LNK_REMOVE }; - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } else { - const SHF_EXCLUDE: u64 = 0x80000000; - let mut file = Object::new(BinaryFormat::Elf, architecture, endianness); - - match &sess.target.arch[..] { - // copied from `mipsel-linux-gnu-gcc foo.c -c` and - // inspecting the resulting `e_flags` field. - "mips" => { - let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; - file.flags = FileFlags::Elf { e_flags }; - } - // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` - "mips64" => { - let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; - file.flags = FileFlags::Elf { e_flags }; - } - - // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though - // that the `+d` target feature represents whether the double - // float abi is enabled. - "riscv64" if sess.target.options.features.contains("+d") => { - let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; - file.flags = FileFlags::Elf { e_flags }; - } - - _ => {} - } - - let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug); - file.section_mut(section).flags = SectionFlags::Elf { sh_flags: SHF_EXCLUDE }; - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } - } } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -635,57 +529,108 @@ }) } -const LLVM_DWP_EXECUTABLE: &'static str = "rust-llvm-dwp"; +/// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a +/// DWARF package. +fn link_dwarf_object<'a>( + sess: &'a Session, + cg_results: &CodegenResults, + executable_out_filename: &Path, +) { + let dwp_out_filename = executable_out_filename.with_extension("dwp"); + debug!(?dwp_out_filename, ?executable_out_filename); -/// Invoke `llvm-dwp` (shipped alongside rustc) to link `dwo` files from Split DWARF into a `dwp` -/// file. -fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) { - info!("preparing dwp to {}.dwp", executable_out_filename.to_str().unwrap()); + #[derive(Default)] + struct ThorinSession { + arena_data: TypedArena>, + arena_mmap: TypedArena, + arena_relocations: TypedArena, + } - let dwp_out_filename = executable_out_filename.with_extension("dwp"); - let mut cmd = Command::new(LLVM_DWP_EXECUTABLE); - cmd.arg("-e"); - cmd.arg(executable_out_filename); - cmd.arg("-o"); - cmd.arg(&dwp_out_filename); - - let mut new_path = sess.get_tools_search_paths(false); - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); + impl ThorinSession { + fn alloc_mmap<'arena>(&'arena self, data: Mmap) -> &'arena Mmap { + (*self.arena_mmap.alloc(data)).borrow() + } } - let new_path = env::join_paths(new_path).unwrap(); - cmd.env("PATH", new_path); - info!("{:?}", &cmd); - match sess.time("run_dwp", || cmd.output()) { - Ok(prog) if !prog.status.success() => { - sess.struct_err(&format!( - "linking dwarf objects with `{}` failed: {}", - LLVM_DWP_EXECUTABLE, prog.status - )) - .note(&format!("{:?}", &cmd)) - .note(&escape_stdout_stderr_string(&prog.stdout)) - .note(&escape_stdout_stderr_string(&prog.stderr)) - .emit(); - info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr)); - info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout)); + impl thorin::Session for ThorinSession { + fn alloc_data<'arena>(&'arena self, data: Vec) -> &'arena [u8] { + (*self.arena_data.alloc(data)).borrow() } - Ok(_) => {} - Err(e) => { - let dwp_not_found = e.kind() == io::ErrorKind::NotFound; - let mut err = if dwp_not_found { - sess.struct_err(&format!("linker `{}` not found", LLVM_DWP_EXECUTABLE)) - } else { - sess.struct_err(&format!("could not exec the linker `{}`", LLVM_DWP_EXECUTABLE)) - }; - err.note(&e.to_string()); + fn alloc_relocation<'arena>(&'arena self, data: Relocations) -> &'arena Relocations { + (*self.arena_relocations.alloc(data)).borrow() + } + + fn read_input<'arena>(&'arena self, path: &Path) -> std::io::Result<&'arena [u8]> { + let file = File::open(&path)?; + let mmap = (unsafe { Mmap::map(file) })?; + Ok(self.alloc_mmap(mmap)) + } + } + + match sess.time("run_thorin", || -> Result<(), thorin::Error> { + let thorin_sess = ThorinSession::default(); + let mut package = thorin::DwarfPackage::new(&thorin_sess); - if !dwp_not_found { - err.note(&format!("{:?}", &cmd)); + // Input objs contain .o/.dwo files from the current crate. + match sess.opts.debugging_opts.split_dwarf_kind { + SplitDwarfKind::Single => { + for input_obj in cg_results.modules.iter().filter_map(|m| m.object.as_ref()) { + package.add_input_object(input_obj)?; + } + } + SplitDwarfKind::Split => { + for input_obj in cg_results.modules.iter().filter_map(|m| m.dwarf_object.as_ref()) { + package.add_input_object(input_obj)?; + } } + } + + // Input rlibs contain .o/.dwo files from dependencies. + let input_rlibs = cg_results + .crate_info + .used_crate_source + .values() + .filter_map(|csource| csource.rlib.as_ref()) + .map(|(path, _)| path); + for input_rlib in input_rlibs { + debug!(?input_rlib); + package.add_input_object(input_rlib)?; + } + + // Failing to read the referenced objects is expected for dependencies where the path in the + // executable will have been cleaned by Cargo, but the referenced objects will be contained + // within rlibs provided as inputs. + // + // If paths have been remapped, then .o/.dwo files from the current crate also won't be + // found, but are provided explicitly above. + // + // Adding an executable is primarily done to make `thorin` check that all the referenced + // dwarf objects are found in the end. + package.add_executable( + &executable_out_filename, + thorin::MissingReferencedObjectBehaviour::Skip, + )?; + + let output = package.finish()?.write()?; + let mut output_stream = BufWriter::new( + OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(true) + .open(dwp_out_filename)?, + ); + output_stream.write_all(&output)?; + output_stream.flush()?; - err.emit(); + Ok(()) + }) { + Ok(()) => {} + Err(e) => { + sess.struct_err("linking dwarf objects with thorin failed") + .note(&format!("{:?}", e)) + .emit(); } } } @@ -1031,7 +976,11 @@ SplitDebuginfo::Packed if sess.target.is_like_msvc => {} // ... and otherwise we're processing a `*.dwp` packed dwarf file. - SplitDebuginfo::Packed => link_dwarf_object(sess, &out_filename), + // + // We cannot rely on the .o paths in the exectuable because they may have been + // remapped by --remap-path-prefix and therefore invalid, so we need to provide + // the .o/.dwo paths explicitly. + SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename), } let strip = strip_value(sess); @@ -1262,26 +1211,36 @@ bug!("Not enough information provided to determine how to invoke the linker"); } -/// Returns a boolean indicating whether we should preserve the object files on -/// the filesystem for their debug information. This is often useful with -/// split-dwarf like schemes. -fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { +/// Returns a pair of boolean indicating whether we should preserve the object and +/// dwarf object files on the filesystem for their debug information. This is often +/// useful with split-dwarf like schemes. +fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) { // If the objects don't have debuginfo there's nothing to preserve. if sess.opts.debuginfo == config::DebugInfo::None { - return false; + return (false, false); } // If we're only producing artifacts that are archives, no need to preserve // the objects as they're losslessly contained inside the archives. - let output_linked = - sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib); - if !output_linked { - return false; + if sess.crate_types().iter().all(|&x| x.is_archive()) { + return (false, false); } - // "unpacked" split debuginfo means that we leave object files as the - // debuginfo is found in the original object files themselves - sess.split_debuginfo() == SplitDebuginfo::Unpacked + match (sess.split_debuginfo(), sess.opts.debugging_opts.split_dwarf_kind) { + // If there is no split debuginfo then do not preserve objects. + (SplitDebuginfo::Off, _) => (false, false), + // If there is packed split debuginfo, then the debuginfo in the objects + // has been packaged and the objects can be deleted. + (SplitDebuginfo::Packed, _) => (false, false), + // If there is unpacked split debuginfo and the current target can not use + // split dwarf, then keep objects. + (SplitDebuginfo::Unpacked, _) if !sess.target_can_use_split_dwarf() => (true, false), + // If there is unpacked split debuginfo and the target can use split dwarf, then + // keep the object containing that debuginfo (whether that is an object file or + // dwarf object file depends on the split dwarf kind). + (SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => (true, false), + (SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => (false, true), + } } fn archive_search_paths(sess: &Session) -> Vec { @@ -2359,8 +2318,8 @@ continue; } - let canonical = f.replace("-", "_"); - let canonical_name = name.replace("-", "_"); + let canonical = f.replace('-', "_"); + let canonical_name = name.replace('-', "_"); let is_rust_object = canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/metadata.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/metadata.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/metadata.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/metadata.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,14 +1,25 @@ //! Reading of the rustc metadata for rlibs and dylibs use std::fs::File; +use std::io::Write; use std::path::Path; -use object::{Object, ObjectSection}; +use object::write::{self, StandardSegment, Symbol, SymbolSection}; +use object::{ + elf, pe, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, + SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, +}; + +use snap::write::FrameEncoder; + use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::rustc_erase_owner; use rustc_data_structures::sync::MetadataRef; +use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; +use rustc_session::Session; +use rustc_target::abi::Endian; use rustc_target::spec::Target; use crate::METADATA_FILENAME; @@ -83,3 +94,193 @@ .data() .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e)) } + +fn create_object_file(sess: &Session) -> Option { + let endianness = match sess.target.options.endian { + Endian::Little => Endianness::Little, + Endian::Big => Endianness::Big, + }; + let architecture = match &sess.target.arch[..] { + "arm" => Architecture::Arm, + "aarch64" => Architecture::Aarch64, + "x86" => Architecture::I386, + "s390x" => Architecture::S390x, + "mips" => Architecture::Mips, + "mips64" => Architecture::Mips64, + "x86_64" => { + if sess.target.pointer_width == 32 { + Architecture::X86_64_X32 + } else { + Architecture::X86_64 + } + } + "powerpc" => Architecture::PowerPc, + "powerpc64" => Architecture::PowerPc64, + "riscv32" => Architecture::Riscv32, + "riscv64" => Architecture::Riscv64, + "sparc64" => Architecture::Sparc64, + // Unsupported architecture. + _ => return None, + }; + let binary_format = if sess.target.is_like_osx { + BinaryFormat::MachO + } else if sess.target.is_like_windows { + BinaryFormat::Coff + } else { + BinaryFormat::Elf + }; + + let mut file = write::Object::new(binary_format, architecture, endianness); + match architecture { + Architecture::Mips => { + // copied from `mipsel-linux-gnu-gcc foo.c -c` and + // inspecting the resulting `e_flags` field. + let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; + file.flags = FileFlags::Elf { e_flags }; + } + Architecture::Mips64 => { + // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` + let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; + file.flags = FileFlags::Elf { e_flags }; + } + Architecture::Riscv64 if sess.target.options.features.contains("+d") => { + // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though + // that the `+d` target feature represents whether the double + // float abi is enabled. + let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; + file.flags = FileFlags::Elf { e_flags }; + } + _ => {} + }; + Some(file) +} + +// For rlibs we "pack" rustc metadata into a dummy object file. When rustc +// creates a dylib crate type it will pass `--whole-archive` (or the +// platform equivalent) to include all object files from an rlib into the +// final dylib itself. This causes linkers to iterate and try to include all +// files located in an archive, so if metadata is stored in an archive then +// it needs to be of a form that the linker will be able to process. +// +// Note, though, that we don't actually want this metadata to show up in any +// final output of the compiler. Instead this is purely for rustc's own +// metadata tracking purposes. +// +// With the above in mind, each "flavor" of object format gets special +// handling here depending on the target: +// +// * MachO - macos-like targets will insert the metadata into a section that +// is sort of fake dwarf debug info. Inspecting the source of the macos +// linker this causes these sections to be skipped automatically because +// it's not in an allowlist of otherwise well known dwarf section names to +// go into the final artifact. +// +// * WebAssembly - we actually don't have any container format for this +// target. WebAssembly doesn't support the `dylib` crate type anyway so +// there's no need for us to support this at this time. Consequently the +// metadata bytes are simply stored as-is into an rlib. +// +// * COFF - Windows-like targets create an object with a section that has +// the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker +// ever sees the section it doesn't process it and it's removed. +// +// * ELF - All other targets are similar to Windows in that there's a +// `SHF_EXCLUDE` flag we can set on sections in an object file to get +// automatically removed from the final output. +pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { + let mut file = if let Some(file) = create_object_file(sess) { + file + } else { + // This is used to handle all "other" targets. This includes targets + // in two categories: + // + // * Some targets don't have support in the `object` crate just yet + // to write an object file. These targets are likely to get filled + // out over time. + // + // * Targets like WebAssembly don't support dylibs, so the purpose + // of putting metadata in object files, to support linking rlibs + // into dylibs, is moot. + // + // In both of these cases it means that linking into dylibs will + // not be supported by rustc. This doesn't matter for targets like + // WebAssembly and for targets not supported by the `object` crate + // yet it means that work will need to be done in the `object` crate + // to add a case above. + return metadata.to_vec(); + }; + let section = file.add_section( + file.segment_name(StandardSegment::Debug).to_vec(), + b".rmeta".to_vec(), + SectionKind::Debug, + ); + match file.format() { + BinaryFormat::Coff => { + file.section_mut(section).flags = + SectionFlags::Coff { characteristics: pe::IMAGE_SCN_LNK_REMOVE }; + } + BinaryFormat::Elf => { + file.section_mut(section).flags = + SectionFlags::Elf { sh_flags: elf::SHF_EXCLUDE as u64 }; + } + _ => {} + }; + file.append_section_data(section, metadata, 1); + file.write().unwrap() +} + +// Historical note: +// +// When using link.exe it was seen that the section name `.note.rustc` +// was getting shortened to `.note.ru`, and according to the PE and COFF +// specification: +// +// > Executable images do not use a string table and do not support +// > section names longer than 8 characters +// +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +// +// As a result, we choose a slightly shorter name! As to why +// `.note.rustc` works on MinGW, see +// https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 +pub fn create_compressed_metadata_file( + sess: &Session, + metadata: &EncodedMetadata, + symbol_name: &str, +) -> Vec { + let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); + FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); + let mut file = if let Some(file) = create_object_file(sess) { + file + } else { + return compressed.to_vec(); + }; + let section = file.add_section( + file.segment_name(StandardSegment::Data).to_vec(), + b".rustc".to_vec(), + SectionKind::ReadOnlyData, + ); + match file.format() { + BinaryFormat::Elf => { + // Explicitly set no flags to avoid SHF_ALLOC default for data section. + file.section_mut(section).flags = SectionFlags::Elf { sh_flags: 0 }; + } + _ => {} + }; + let offset = file.append_section_data(section, &compressed, 1); + + // For MachO and probably PE this is necessary to prevent the linker from throwing away the + // .rustc section. For ELF this isn't necessary, but it also doesn't harm. + file.add_symbol(Symbol { + name: symbol_name.as_bytes().to_vec(), + value: offset, + size: compressed.len() as u64, + kind: SymbolKind::Data, + scope: SymbolScope::Dynamic, + weak: false, + section: SymbolSection::Section(section), + flags: SymbolFlags::None, + }); + + file.write().unwrap() +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/rpath.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/rpath.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/rpath.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/rpath.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,9 +23,12 @@ let rpaths = get_rpaths(config); let mut flags = rpaths_to_flags(&rpaths); - // Use DT_RUNPATH instead of DT_RPATH if available if config.linker_is_gnu { + // Use DT_RUNPATH instead of DT_RPATH if available flags.push("-Wl,--enable-new-dtags".to_owned()); + + // Set DF_ORIGIN for substitute $ORIGIN + flags.push("-Wl,-z,origin".to_owned()); } flags diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs 2022-02-23 04:07:21.000000000 +0000 @@ -154,7 +154,7 @@ tcx.reachable_non_generics(def_id.krate).contains_key(&def_id) } -fn exported_symbols_provider_local( +fn exported_symbols_provider_local<'tcx>( tcx: TyCtxt<'tcx>, cnum: CrateNum, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/write.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/write.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/write.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/back/write.rs 2022-02-23 04:07:21.000000000 +0000 @@ -113,6 +113,7 @@ pub inline_threshold: Option, pub new_llvm_pass_manager: Option, pub emit_lifetime_markers: bool, + pub llvm_plugins: Vec, } impl ModuleConfig { @@ -260,6 +261,7 @@ inline_threshold: sess.opts.cg.inline_threshold, new_llvm_pass_manager: sess.opts.debugging_opts.new_llvm_pass_manager, emit_lifetime_markers: sess.emit_lifetime_markers(), + llvm_plugins: if_regular!(sess.opts.debugging_opts.llvm_plugins.clone(), vec![]), } } @@ -284,7 +286,11 @@ module_name: &str, ) -> TargetMachineFactoryConfig { let split_dwarf_file = if cgcx.target_can_use_split_dwarf { - cgcx.output_filenames.split_dwarf_path(cgcx.split_debuginfo, Some(module_name)) + cgcx.output_filenames.split_dwarf_path( + cgcx.split_debuginfo, + cgcx.split_dwarf_kind, + Some(module_name), + ) } else { None }; @@ -327,6 +333,7 @@ pub target_arch: String, pub debuginfo: config::DebugInfo, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, + pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -397,7 +404,6 @@ pub struct CompiledModules { pub modules: Vec, - pub metadata_module: Option, pub allocator_module: Option, } @@ -425,6 +431,7 @@ tcx: TyCtxt<'_>, target_cpu: String, metadata: EncodedMetadata, + metadata_module: Option, total_cgus: usize, ) -> OngoingCodegen { let (coordinator_send, coordinator_receive) = channel(); @@ -464,6 +471,7 @@ OngoingCodegen { backend, metadata, + metadata_module, crate_info, coordinator_send, @@ -640,12 +648,6 @@ } if !user_wants_bitcode { - if let Some(ref metadata_module) = compiled_modules.metadata_module { - if let Some(ref path) = metadata_module.bytecode { - ensure_removed(sess.diagnostic(), &path); - } - } - if let Some(ref allocator_module) = compiled_modules.allocator_module { if let Some(ref path) = allocator_module.bytecode { ensure_removed(sess.diagnostic(), path); @@ -682,11 +684,11 @@ fn start_profiling<'a>(&self, cgcx: &'a CodegenContext) -> TimingGuard<'a> { match *self { WorkItem::Optimize(ref m) => { - cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &m.name[..]) + cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name) } WorkItem::CopyPostLtoArtifacts(ref m) => cgcx .prof - .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &m.name[..]), + .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*m.name), WorkItem::LTO(ref m) => { cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name()) } @@ -1063,6 +1065,7 @@ target_arch: tcx.sess.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, split_debuginfo: tcx.sess.split_debuginfo(), + split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf_kind, }; // This is the "main loop" of parallel work happening for parallel codegen. @@ -1216,7 +1219,6 @@ // This is where we collect codegen units that have gone all the way // through codegen and LLVM. let mut compiled_modules = vec![]; - let mut compiled_metadata_module = None; let mut compiled_allocator_module = None; let mut needs_link = Vec::new(); let mut needs_fat_lto = Vec::new(); @@ -1475,14 +1477,11 @@ ModuleKind::Regular => { compiled_modules.push(compiled_module); } - ModuleKind::Metadata => { - assert!(compiled_metadata_module.is_none()); - compiled_metadata_module = Some(compiled_module); - } ModuleKind::Allocator => { assert!(compiled_allocator_module.is_none()); compiled_allocator_module = Some(compiled_module); } + ModuleKind::Metadata => bug!("Should be handled separately"), } } Message::NeedsLink { module, worker_id } => { @@ -1539,7 +1538,6 @@ Ok(CompiledModules { modules: compiled_modules, - metadata_module: compiled_metadata_module, allocator_module: compiled_allocator_module, }) }); @@ -1800,6 +1798,7 @@ pub struct OngoingCodegen { pub backend: B, pub metadata: EncodedMetadata, + pub metadata_module: Option, pub crate_info: CrateInfo, pub coordinator_send: Sender>, pub codegen_worker_receive: Receiver>, @@ -1846,7 +1845,7 @@ modules: compiled_modules.modules, allocator_module: compiled_modules.allocator_module, - metadata_module: compiled_modules.metadata_module, + metadata_module: self.metadata_module, }, work_products, ) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/base.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,4 @@ +use crate::back::metadata::create_compressed_metadata_file; use crate::back::write::{ compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, @@ -8,7 +9,7 @@ use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; -use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; +use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; @@ -20,13 +21,14 @@ use rustc_index::vec::Idx; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::exported_symbols; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{self, EntryFnType}; +use rustc_session::config::{self, EntryFnType, OutputType}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_target::abi::{Align, VariantIdx}; @@ -484,14 +486,14 @@ pub fn codegen_crate( backend: B, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, target_cpu: String, metadata: EncodedMetadata, need_metadata_module: bool, ) -> OngoingCodegen { // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { - let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, 1); + let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1); ongoing_codegen.codegen_finished(tcx); @@ -517,8 +519,41 @@ } } - let ongoing_codegen = - start_async_codegen(backend.clone(), tcx, target_cpu, metadata, codegen_units.len()); + let metadata_module = if need_metadata_module { + // Emit compressed metadata object. + let metadata_cgu_name = + cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); + tcx.sess.time("write_compressed_metadata", || { + let file_name = + tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + let data = create_compressed_metadata_file( + tcx.sess, + &metadata, + &exported_symbols::metadata_symbol_name(tcx), + ); + if let Err(err) = std::fs::write(&file_name, data) { + tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); + } + Some(CompiledModule { + name: metadata_cgu_name, + kind: ModuleKind::Metadata, + object: Some(file_name), + dwarf_object: None, + bytecode: None, + }) + }) + } else { + None + }; + + let ongoing_codegen = start_async_codegen( + backend.clone(), + tcx, + target_cpu, + metadata, + metadata_module, + codegen_units.len(), + ); let ongoing_codegen = AbortCodegenOnDrop::(Some(ongoing_codegen)); // Codegen an allocator shim, if necessary. @@ -558,27 +593,6 @@ ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module); } - if need_metadata_module { - // Codegen the encoded metadata. - let metadata_cgu_name = - cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); - let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); - tcx.sess.time("write_compressed_metadata", || { - backend.write_compressed_metadata( - tcx, - &ongoing_codegen.metadata, - &mut metadata_llvm_module, - ); - }); - - let metadata_module = ModuleCodegen { - name: metadata_cgu_name, - module_llvm: metadata_llvm_module, - kind: ModuleKind::Metadata, - }; - ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module); - } - // For better throughput during parallel processing by LLVM, we used to sort // CGUs largest to smallest. This would lead to better thread utilization // by, for example, preventing a large CGU from being processed last and @@ -658,7 +672,7 @@ } let cgu_reuse = cgu_reuse[i]; - tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); + tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); match cgu_reuse { CguReuse::No => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/common.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/common.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/common.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/common.rs 2022-02-23 04:07:21.000000000 +0000 @@ -122,8 +122,8 @@ tcx.lang_items().require(li).unwrap_or_else(|s| { let msg = format!("{} {}", msg, s); match span { - Some(span) => tcx.sess.span_fatal(span, &msg[..]), - None => tcx.sess.fatal(&msg[..]), + Some(span) => tcx.sess.span_fatal(span, &msg), + None => tcx.sess.fatal(&msg), } }) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,6 @@ use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex}; -/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222) +/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum CounterKind { @@ -17,7 +17,7 @@ /// `instrprof.increment()`) /// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of /// counter expressions. -/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100) +/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103) /// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart. #[derive(Copy, Clone, Debug)] #[repr(C)] @@ -59,7 +59,7 @@ } } -/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147) +/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum ExprKind { @@ -67,7 +67,7 @@ Add = 1, } -/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149) +/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152) /// Important: The Rust struct layout (order and types of fields) must match its C++ /// counterpart. #[derive(Copy, Clone, Debug)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -150,9 +150,9 @@ /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their /// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create /// `CounterMappingRegion`s. - pub fn get_expressions_and_counter_regions<'a>( - &'a self, - ) -> (Vec, impl Iterator) { + pub fn get_expressions_and_counter_regions( + &self, + ) -> (Vec, impl Iterator) { assert!( self.source_hash != 0 || !self.is_used, "No counters provided the source_hash for used function: {:?}", @@ -168,7 +168,7 @@ (counter_expressions, counter_regions) } - fn counter_regions<'a>(&'a self) -> impl Iterator { + fn counter_regions(&self) -> impl Iterator { self.counters.iter_enumerated().filter_map(|(index, entry)| { // Option::map() will return None to filter out missing counters. This may happen // if, for example, a MIR-instrumented counter is removed during an optimization. @@ -177,8 +177,8 @@ } fn expressions_with_regions( - &'a self, - ) -> (Vec, impl Iterator) { + &self, + ) -> (Vec, impl Iterator) { let mut counter_expressions = Vec::with_capacity(self.expressions.len()); let mut expression_regions = Vec::with_capacity(self.expressions.len()); let mut new_indexes = IndexVec::from_elem_n(None, self.expressions.len()); @@ -336,7 +336,7 @@ (counter_expressions, expression_regions.into_iter()) } - fn unreachable_regions<'a>(&'a self) -> impl Iterator { + fn unreachable_regions(&self) -> impl Iterator { self.unreachable_regions.iter().map(|region| (Counter::zero(), region)) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs 2022-02-23 04:07:21.000000000 +0000 @@ -53,14 +53,14 @@ ) { // When targeting MSVC, emit C++ style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("never$"); } else { output.push('!'); @@ -71,7 +71,7 @@ ty::Float(float_ty) => output.push_str(float_ty.name_str()), ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), ty::Adt(def, substs) => { - if def.is_enum() && cpp_like_names { + if def.is_enum() && cpp_like_debuginfo { msvc_enum_fallback(tcx, t, def, substs, output, visited); } else { push_item_name(tcx, def.did, qualified, output); @@ -79,7 +79,7 @@ } } ty::Tuple(component_types) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("tuple$<"); } else { output.push('('); @@ -87,20 +87,20 @@ for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } if !component_types.is_empty() { pop_arg_separator(output); } - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else { output.push(')'); } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { - if cpp_like_names { + if cpp_like_debuginfo { match mutbl { hir::Mutability::Not => output.push_str("ptr_const$<"), hir::Mutability::Mut => output.push_str("ptr_mut$<"), @@ -115,8 +115,8 @@ push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } } ty::Ref(_, inner_type, mutbl) => { @@ -126,7 +126,7 @@ // types out to aid debugging in MSVC. let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); - if !cpp_like_names { + if !cpp_like_debuginfo { output.push('&'); output.push_str(mutbl.prefix_str()); } else if !is_slice_or_str { @@ -138,12 +138,12 @@ push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names && !is_slice_or_str { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo && !is_slice_or_str { + push_close_angle_bracket(cpp_like_debuginfo, output); } } ty::Array(inner_type, len) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("array$<"); push_debuginfo_type_name(tcx, inner_type, true, output, visited); match len.val { @@ -162,7 +162,7 @@ } } ty::Slice(inner_type) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("slice$<"); } else { output.push('['); @@ -170,8 +170,8 @@ push_debuginfo_type_name(tcx, inner_type, true, output, visited); - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else { output.push(']'); } @@ -179,7 +179,7 @@ ty::Dynamic(ref trait_data, ..) => { let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); - let has_enclosing_parens = if cpp_like_names { + let has_enclosing_parens = if cpp_like_debuginfo { output.push_str("dyn$<"); false } else { @@ -216,14 +216,14 @@ } for (item_def_id, ty) in projection_bounds { - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("assoc$<"); push_item_name(tcx, item_def_id, false, output); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); push_debuginfo_type_name(tcx, ty, true, output, visited); - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); } else { push_item_name(tcx, item_def_id, false, output); output.push('='); @@ -231,11 +231,11 @@ } } - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); } if auto_traits.len() != 0 { - push_auto_trait_separator(cpp_like_names, output); + push_auto_trait_separator(cpp_like_debuginfo, output); } } @@ -252,14 +252,14 @@ for auto_trait in auto_traits { output.push_str(&auto_trait); - push_auto_trait_separator(cpp_like_names, output); + push_auto_trait_separator(cpp_like_debuginfo, output); } pop_auto_trait_separator(output); } - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else if has_enclosing_parens { output.push(')'); } @@ -279,7 +279,7 @@ // use a dummy string that should make it clear // that something unusual is going on if !visited.insert(t) { - output.push_str(if cpp_like_names { + output.push_str(if cpp_like_debuginfo { "recursive_type$" } else { "" @@ -290,7 +290,7 @@ let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); - if cpp_like_names { + if cpp_like_debuginfo { // Format as a C++ function pointer: return_type (*)(params...) if sig.output().is_unit() { output.push_str("void"); @@ -313,7 +313,7 @@ if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(tcx, parameter_type, true, output, visited); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } pop_arg_separator(output); } @@ -328,7 +328,7 @@ output.push(')'); - if !cpp_like_names && !sig.output().is_unit() { + if !cpp_like_debuginfo && !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(tcx, sig.output(), true, output, visited); } @@ -376,7 +376,7 @@ // format (natvis) is able to understand enums and render the active variant correctly in the // debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and // `EnumMemberDescriptionFactor::create_member_descriptions`. - fn msvc_enum_fallback( + fn msvc_enum_fallback<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, def: &AdtDef, @@ -426,9 +426,9 @@ const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + "; - fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) { - if cpp_like_names { - push_arg_separator(cpp_like_names, output); + fn push_auto_trait_separator(cpp_like_debuginfo: bool, output: &mut String) { + if cpp_like_debuginfo { + push_arg_separator(cpp_like_debuginfo, output); } else { output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR); } @@ -457,11 +457,11 @@ t: Ty<'tcx>, trait_ref: Option>, ) -> String { - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); let mut vtable_name = String::with_capacity(64); - if cpp_like_names { + if cpp_like_debuginfo { vtable_name.push_str("impl$<"); } else { vtable_name.push('<'); @@ -470,7 +470,7 @@ let mut visited = FxHashSet::default(); push_debuginfo_type_name(tcx, t, true, &mut vtable_name, &mut visited); - if cpp_like_names { + if cpp_like_debuginfo { vtable_name.push_str(", "); } else { vtable_name.push_str(" as "); @@ -486,9 +486,9 @@ vtable_name.push_str("_"); } - push_close_angle_bracket(cpp_like_names, &mut vtable_name); + push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name); - let suffix = if cpp_like_names { "::vtable$" } else { "::{vtable}" }; + let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" }; vtable_name.reserve_exact(suffix.len()); vtable_name.push_str(suffix); @@ -496,7 +496,7 @@ vtable_name } -pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { +pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &mut String) { let def_key = tcx.def_key(def_id); if qualified { if let Some(parent) = def_key.parent { @@ -509,19 +509,19 @@ } fn push_unqualified_item_name( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, def_id: DefId, disambiguated_data: DisambiguatedDefPathData, output: &mut String, ) { match disambiguated_data.data { DefPathData::CrateRoot => { - output.push_str(&tcx.crate_name(def_id.krate).as_str()); + output.push_str(tcx.crate_name(def_id.krate).as_str()); } DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { // Generators look like closures, but we want to treat them differently // in the debug info. - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); @@ -529,10 +529,10 @@ } _ => match disambiguated_data.data.name() { DefPathDataName::Named(name) => { - output.push_str(&name.as_str()); + output.push_str(name.as_str()); } DefPathDataName::Anon { namespace } => { - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) @@ -560,7 +560,7 @@ debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs)); - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); output.push('<'); @@ -575,10 +575,10 @@ other => bug!("Unexpected non-erasable generic: {:?}", other), } - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } pop_arg_separator(output); - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); true } @@ -617,7 +617,7 @@ // avoiding collisions and will make the emitted type names shorter. let hash: u64 = hasher.finish(); - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "CONST${:x}", hash) } else { write!(output, "{{CONST#{:x}}}", hash) @@ -634,10 +634,10 @@ push_generic_params_internal(tcx, substs, output, &mut visited); } -fn push_close_angle_bracket(cpp_like_names: bool, output: &mut String) { +fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) { // MSVC debugger always treats `>>` as a shift, even when parsing templates, // so add a space to avoid confusion. - if cpp_like_names && output.ends_with('>') { + if cpp_like_debuginfo && output.ends_with('>') { output.push(' ') }; @@ -652,11 +652,11 @@ } } -fn push_arg_separator(cpp_like_names: bool, output: &mut String) { +fn push_arg_separator(cpp_like_debuginfo: bool, output: &mut String) { // Natvis does not always like having spaces between parts of the type name // and this causes issues when we need to write a typename in natvis, for example // as part of a cast like the `HashMap` visualizer does. - if cpp_like_names { + if cpp_like_debuginfo { output.push(','); } else { output.push_str(", "); @@ -673,6 +673,7 @@ output.pop(); } -fn cpp_like_names(tcx: TyCtxt<'_>) -> bool { +/// Check if we should generate C++ like names and debug information. +pub fn cpp_like_debuginfo(tcx: TyCtxt<'_>) -> bool { tcx.sess.target.is_like_msvc } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/glue.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/glue.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/glue.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/glue.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,6 +6,7 @@ use crate::meth; use crate::traits::*; use rustc_middle::ty::{self, Ty}; +use rustc_target::abi::WrappingRange; pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, @@ -21,14 +22,17 @@ } match t.kind() { ty::Dynamic(..) => { - // load size/align from vtable + // Load size/align from vtable. let vtable = info.unwrap(); - ( - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) - .get_usize(bx, vtable), - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) - .get_usize(bx, vtable), - ) + let size = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) + .get_usize(bx, vtable); + let align = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) + .get_usize(bx, vtable); + + // Alignment is always nonzero. + bx.range_metadata(align, WrappingRange { start: 1, end: !0 }); + + (size, align) } ty::Slice(_) | ty::Str => { let unit = layout.field(bx, 0); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(try_blocks)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(once_cell)] #![feature(nll)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/analyze.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/analyze.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/analyze.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/analyze.rs 2022-02-23 04:07:21.000000000 +0000 @@ -73,7 +73,7 @@ locals: IndexVec, } -impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { +impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn assign(&mut self, local: mir::Local, location: Location) { let kind = &mut self.locals[local]; match *kind { @@ -211,6 +211,7 @@ PlaceContext::MutatingUse( MutatingUseContext::Store + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::AsmOutput | MutatingUseContext::Borrow | MutatingUseContext::AddressOf @@ -275,9 +276,9 @@ | TerminatorKind::SwitchInt { .. } | TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => { /* nothing to do */ } + | TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ } TerminatorKind::Call { cleanup: unwind, .. } + | TerminatorKind::InlineAsm { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::DropAndReplace { unwind, .. } | TerminatorKind::Drop { unwind, .. } => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/block.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/block.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/block.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/block.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,6 +10,7 @@ use crate::MemFlags; use rustc_ast as ast; +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::AssertKind; @@ -159,11 +160,7 @@ let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); if fx.mir[self.bb].is_cleanup { - // Cleanup is always the cold path. Don't inline - // drop glue. Also, when there is a deeply-nested - // struct, there are "symmetry" issues that cause - // exponential inlining - see issue #41696. - bx.do_not_inline(llret); + bx.apply_attrs_to_cleanup_callsite(llret); } if let Some((ret_dest, target)) = destination { @@ -174,6 +171,45 @@ } } } + + /// Generates inline assembly with optional `destination` and `cleanup`. + fn do_inlineasm>( + &self, + fx: &mut FunctionCx<'a, 'tcx, Bx>, + bx: &mut Bx, + template: &[InlineAsmTemplatePiece], + operands: &[InlineAsmOperandRef<'tcx, Bx>], + options: InlineAsmOptions, + line_spans: &[Span], + destination: Option, + cleanup: Option, + instance: Instance<'_>, + ) { + if let Some(cleanup) = cleanup { + let ret_llbb = if let Some(target) = destination { + fx.llbb(target) + } else { + fx.unreachable_block() + }; + + bx.codegen_inline_asm( + template, + &operands, + options, + line_spans, + instance, + Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))), + ); + } else { + bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); + + if let Some(target) = destination { + self.funclet_br(fx, bx, target); + } else { + bx.unreachable(); + } + } + } } /// Codegen implementations for some terminator variants. @@ -877,6 +913,7 @@ options: ast::InlineAsmOptions, line_spans: &[Span], destination: Option, + cleanup: Option, instance: Instance<'_>, ) { let span = terminator.source_info.span; @@ -931,13 +968,17 @@ }) .collect(); - bx.codegen_inline_asm(template, &operands, options, line_spans, instance); - - if let Some(target) = destination { - helper.funclet_br(self, &mut bx, target); - } else { - bx.unreachable(); - } + helper.do_inlineasm( + self, + &mut bx, + template, + &operands, + options, + line_spans, + destination, + cleanup, + instance, + ); } } @@ -1041,6 +1082,7 @@ options, line_spans, destination, + cleanup, } => { self.codegen_asm_terminator( helper, @@ -1051,6 +1093,7 @@ options, line_spans, destination, + cleanup, self.instance, ); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs 2022-02-23 04:07:21.000000000 +0000 @@ -68,7 +68,7 @@ let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = bx.tcx().item_name(def_id); - let name_str = &*name.as_str(); + let name_str = name.as_str(); let llret_ty = bx.backend_type(bx.layout_of(ret_ty)); let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); @@ -375,7 +375,7 @@ use crate::common::AtomicOrdering::*; use crate::common::{AtomicRmwBinOp, SynchronizationScope}; - let split: Vec<&str> = name_str.split('_').collect(); + let split: Vec<_> = name_str.split('_').collect(); let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak"; let (order, failorder) = match split.len() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/operand.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/operand.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/operand.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/operand.rs 2022-02-23 04:07:21.000000000 +0000 @@ -47,7 +47,7 @@ pub layout: TyAndLayout<'tcx>, } -impl fmt::Debug for OperandRef<'tcx, V> { +impl fmt::Debug for OperandRef<'_, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,7 +8,6 @@ use crate::MemFlags; use rustc_apfloat::{ieee, Float, Round, Status}; -use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; @@ -112,9 +111,9 @@ mir::Rvalue::Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { dest.codegen_set_discr(&mut bx, variant_index); - if adt_def.is_enum() { + if bx.tcx().adt_def(adt_did).is_enum() { (dest.project_downcast(&mut bx, variant_index), active_field_index) } else { (dest, active_field_index) @@ -486,31 +485,6 @@ ) } - mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { - let content_ty = self.monomorphize(content_ty); - let content_layout = bx.cx().layout_of(content_ty); - let llsize = bx.cx().const_usize(content_layout.size.bytes()); - let llalign = bx.cx().const_usize(content_layout.align.abi.bytes()); - let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); - let llty_ptr = bx.cx().backend_type(box_layout); - - // Allocate space: - let def_id = match bx.tcx().lang_items().require(LangItem::ExchangeMalloc) { - Ok(id) => id, - Err(s) => { - bx.cx().sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s)); - } - }; - let instance = ty::Instance::mono(bx.tcx(), def_id); - let r = bx.cx().get_fn_addr(instance); - let ty = bx.type_func(&[bx.type_isize(), bx.type_isize()], bx.type_i8p()); - let call = bx.call(ty, r, &[llsize, llalign], None); - let val = bx.pointercast(call, llty_ptr); - - let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; - (bx, operand) - } - mir::Rvalue::NullaryOp(null_op, ty) => { let ty = self.monomorphize(ty); assert!(bx.cx().type_is_sized(ty)); @@ -518,7 +492,6 @@ let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), - mir::NullOp::Box => unreachable!(), }; let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/target_features.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/target_features.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/target_features.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/target_features.rs 2022-02-23 04:07:21.000000000 +0000 @@ -35,6 +35,8 @@ // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), + ("thumb2", Some(sym::arm_target_feature)), + ("reserve-r9", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/asm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/asm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/asm.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/asm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -59,6 +59,7 @@ options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, + dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/backend.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/backend.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/backend.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/backend.rs 2022-02-23 04:07:21.000000000 +0000 @@ -97,6 +97,7 @@ &self, ongoing_codegen: Box, sess: &Session, + outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported>; /// This is called on the returned `Box` from `join_codegen` @@ -114,12 +115,6 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; - fn write_compressed_metadata<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut Self::Module, - ); fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -311,5 +311,5 @@ ) -> Self::Value; fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - fn do_not_inline(&mut self, llret: Self::Value); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/type_.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/type_.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/type_.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_codegen_ssa/src/traits/type_.rs 2022-02-23 04:07:21.000000000 +0000 @@ -97,7 +97,7 @@ } } -impl DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} +impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; @@ -135,4 +135,4 @@ pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} -impl TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} +impl<'tcx, T> TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/eval_queries.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/eval_queries.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/eval_queries.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/eval_queries.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,7 @@ }; use rustc_errors::ErrorReported; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; @@ -62,7 +63,7 @@ cid.instance, body, Some(&ret.into()), - StackPopCleanup::None { cleanup: false }, + StackPopCleanup::Root { cleanup: false }, )?; // The main interpreter loop. @@ -215,6 +216,7 @@ tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // see comment in eval_to_allocation_raw_provider for what we're doing here if key.param_env.reveal() == Reveal::All { let mut key = key; @@ -249,6 +251,7 @@ tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // Because the constant is computed twice (once per value of `Reveal`), we are at risk of // reporting the same error twice here. To resolve this, we check whether we can evaluate the // constant in the more restrictive `Reveal::UserFacing`, which most likely already was diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/machine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/machine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/machine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/machine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -260,7 +260,7 @@ args: &[OpTy<'tcx>], _ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>, _unwind: StackPopUnwind, // unwinding is not supported in consts - ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> { + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { debug!("find_mir_or_eval_fn: {:?}", instance); // Only check non-glue functions @@ -279,11 +279,21 @@ if let Some(new_instance) = ecx.hook_special_const_fn(instance, args)? { // We call another const fn instead. - return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind); + // However, we return the *original* instance to make backtraces work out + // (and we hope this does not confuse the FnAbi checks too much). + return Ok(Self::find_mir_or_eval_fn( + ecx, + new_instance, + _abi, + args, + _ret, + _unwind, + )? + .map(|(body, _instance)| (body, instance))); } } // This is a const fn. Call it. - Ok(Some(ecx.load_mir(instance.def, None)?)) + Ok(Some((ecx.load_mir(instance.def, None)?, instance))) } fn call_intrinsic( @@ -388,13 +398,6 @@ Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } - fn box_alloc( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _dest: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) - } - fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { // The step limit has already been hit in a previous call to `before_terminator`. if ecx.machine.steps_remaining == 0 { @@ -423,14 +426,14 @@ } #[inline(always)] - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] { &ecx.machine.stack } #[inline(always)] - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec> { &mut ecx.machine.stack diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/const_eval/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -25,9 +25,9 @@ pub use machine::*; pub(crate) fn const_caller_location( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, (file, line, col): (Symbol, u32, u32), -) -> ConstValue<'tcx> { +) -> ConstValue<'_> { trace!("const_caller_location: {}:{}:{}", file, line, col); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/eval_context.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/eval_context.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/eval_context.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/eval_context.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,11 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_middle::mir; -use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo}; +use rustc_middle::ty::layout::{ + self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, + TyAndLayout, +}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, }; @@ -15,7 +19,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_session::Limit; use rustc_span::{Pos, Span}; -use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; +use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, @@ -152,11 +156,11 @@ /// `ret` stores the block we jump to on a normal return, while `unwind` /// stores the block used for cleanup during unwinding. Goto { ret: Option, unwind: StackPopUnwind }, - /// Just do nothing: Used by Main and for the `box_alloc` hook in miri. + /// The root frame of the stack: nowhere else to jump to. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away /// the entire `ecx` when it is done). - None { cleanup: bool }, + Root { cleanup: bool }, } /// State of a local variable including a memoized layout @@ -332,6 +336,24 @@ } } +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> { + type FnAbiOfResult = InterpResult<'tcx, &'tcx FnAbi<'tcx, Ty<'tcx>>>; + + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + _span: Span, + _fn_abi_request: FnAbiRequest<'tcx>, + ) -> InterpErrorInfo<'tcx> { + match err { + FnAbiError::Layout(err) => err_inval!(Layout(err)).into(), + FnAbiError::AdjustForForeignAbi(err) => { + err_inval!(FnAbiAdjustForForeignAbi(err)).into() + } + } + } +} + /// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value. /// This test should be symmetric, as it is primarily about layout compatibility. pub(super) fn mir_assign_valid_types<'tcx>( @@ -508,7 +530,7 @@ pub(super) fn subst_from_current_frame_and_normalize_erasing_regions>( &self, value: T, - ) -> T { + ) -> Result> { self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value) } @@ -518,8 +540,18 @@ &self, frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, value: T, - ) -> T { - frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + ) -> Result> { + frame + .instance + .try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + .or_else(|e| { + self.tcx.sess.delay_span_bug( + self.cur_span(), + format!("failed to normalize {}", e.get_type_for_failure()).as_str(), + ); + + Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric)) + }) } /// The `substs` are assumed to already be in our interpreter "universe" (param_env). @@ -554,7 +586,7 @@ let layout = from_known_layout(self.tcx, self.param_env, layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = - self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty); + self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?; self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { @@ -605,19 +637,9 @@ match self.size_and_align_of(metadata, &field)? { Some(size_and_align) => size_and_align, None => { - // A field with extern type. If this field is at offset 0, we behave - // like the underlying extern type. - // FIXME: Once we have made decisions for how to handle size and alignment - // of `extern type`, this should be adapted. It is just a temporary hack - // to get some code to work that probably ought to work. - if sized_size == Size::ZERO { - return Ok(None); - } else { - span_bug!( - self.cur_span(), - "Fields cannot be extern types, unless they are at offset 0" - ) - } + // A field with an extern type. We don't know the actual dynamic size + // or the alignment. + return Ok(None); } }; @@ -702,7 +724,7 @@ for const_ in &body.required_consts { let span = const_.span; let const_ = - self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?; self.mir_const_to_op(&const_, None).map_err(|err| { // If there was an error, set the span of the current frame to this constant. // Avoiding doing this when evaluation succeeds. @@ -827,7 +849,7 @@ // because this is CTFE and the final value will be thoroughly validated anyway. let cleanup = match return_to_block { StackPopCleanup::Goto { .. } => true, - StackPopCleanup::None { cleanup, .. } => cleanup, + StackPopCleanup::Root { cleanup, .. } => cleanup, }; if !cleanup { @@ -852,8 +874,8 @@ // Follow the unwind edge. let unwind = match return_to_block { StackPopCleanup::Goto { unwind, .. } => unwind, - StackPopCleanup::None { .. } => { - panic!("Encountered StackPopCleanup::None when unwinding!") + StackPopCleanup::Root { .. } => { + panic!("encountered StackPopCleanup::Root when unwinding!") } }; self.unwind_to_block(unwind) @@ -861,7 +883,13 @@ // Follow the normal return edge. match return_to_block { StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret), - StackPopCleanup::None { .. } => Ok(()), + StackPopCleanup::Root { .. } => { + assert!( + self.stack().is_empty(), + "only the topmost frame can have StackPopCleanup::Root" + ); + Ok(()) + } } } } @@ -918,12 +946,13 @@ } else { self.param_env }; + let param_env = param_env.with_const(); let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } #[must_use] - pub fn dump_place(&'a self, place: Place) -> PlacePrinter<'a, 'mir, 'tcx, M> { + pub fn dump_place(&self, place: Place) -> PlacePrinter<'_, 'mir, 'tcx, M> { PlacePrinter { ecx: self, place } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intern.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intern.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intern.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intern.rs 2022-02-23 04:07:21.000000000 +0000 @@ -292,14 +292,15 @@ /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures /// are hard errors. #[tracing::instrument(level = "debug", skip(ecx))] -pub fn intern_const_alloc_recursive>( +pub fn intern_const_alloc_recursive< + 'mir, + 'tcx: 'mir, + M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>, +>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: &MPlaceTy<'tcx>, -) -> Result<(), ErrorReported> -where - 'tcx: 'mir, -{ +) -> Result<(), ErrorReported> { let tcx = ecx.tcx; let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs 2022-02-23 04:07:21.000000000 +0000 @@ -82,7 +82,7 @@ ) -> MPlaceTy<'tcx, M::PointerTag> { let loc_details = &self.tcx.sess.opts.debugging_opts.location_detail; let file = if loc_details.file { - self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not) + self.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not) } else { // FIXME: This creates a new allocation each time. It might be preferable to // perform this allocation only once, and re-use the `MPlaceTy`. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs 2022-02-23 04:07:21.000000000 +0000 @@ -88,7 +88,7 @@ } fn path_crate(mut self, cnum: CrateNum) -> Result { - self.path.push_str(&self.tcx.crate_name(cnum).as_str()); + self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -148,7 +148,7 @@ } } -impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/intrinsics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -140,7 +140,7 @@ sym::min_align_of_val | sym::size_of_val => { // Avoid `deref_operand` -- this is not a deref, the ptr does not have to be - // dereferencable! + // dereferenceable! let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?; let (size, align) = self .size_and_align_of_mplace(&place)? @@ -322,6 +322,9 @@ sym::copy => { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } + sym::write_bytes => { + self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; + } sym::offset => { let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; @@ -394,10 +397,12 @@ sym::transmute => { self.copy_op_transmute(&args[0], dest)?; } - sym::assert_inhabited => { + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { let ty = instance.substs.type_at(0); let layout = self.layout_of(ty)?; + // For *all* intrinsics we first check `is_uninhabited` to give a more specific + // error message. if layout.abi.is_uninhabited() { // The run-time intrinsic panics just to get a good backtrace; here we abort // since there is no problem showing a backtrace even for aborts. @@ -409,6 +414,28 @@ ), )?; } + if intrinsic_name == sym::assert_zero_valid + && !layout.might_permit_raw_init(self, /*zero:*/ true) + { + M::abort( + self, + format!( + "aborted execution: attempted to zero-initialize type `{}`, which is invalid", + ty + ), + )?; + } + if intrinsic_name == sym::assert_uninit_valid + && !layout.might_permit_raw_init(self, /*zero:*/ false) + { + M::abort( + self, + format!( + "aborted execution: attempted to leave type `{}` uninitialized, which is invalid", + ty + ), + )?; + } } sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); @@ -543,6 +570,27 @@ self.memory.copy(src, align, dst, align, size, nonoverlapping) } + pub(crate) fn write_bytes_intrinsic( + &mut self, + dst: &OpTy<'tcx, >::PointerTag>, + byte: &OpTy<'tcx, >::PointerTag>, + count: &OpTy<'tcx, >::PointerTag>, + ) -> InterpResult<'tcx> { + let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?; + + let dst = self.read_pointer(&dst)?; + let byte = self.read_scalar(&byte)?.to_u8()?; + let count = self.read_scalar(&count)?.to_machine_usize(self)?; + + let len = layout + .size + .checked_mul(count, self) + .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?; + + let bytes = std::iter::repeat(byte).take(len.bytes_usize()); + self.memory.write_bytes(dst, bytes) + } + pub(crate) fn raw_eq_intrinsic( &mut self, lhs: &OpTy<'tcx, >::PointerTag>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/machine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/machine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/machine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/machine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -167,7 +167,7 @@ args: &[OpTy<'tcx, Self::PointerTag>], ret: Option<(&PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>, unwind: StackPopUnwind, - ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>>; + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; /// Execute `fn_val`. It is the hook's responsibility to advance the instruction /// pointer as appropriate. @@ -212,12 +212,6 @@ right: &ImmTy<'tcx, Self::PointerTag>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)>; - /// Heap allocations via the `box` keyword. - fn box_alloc( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - dest: &PlaceTy<'tcx, Self::PointerTag>, - ) -> InterpResult<'tcx>; - /// Called to read the specified `local` from the `frame`. /// Since reading a ZST is not actually accessing memory or locals, this is never invoked /// for ZST reads. @@ -374,12 +368,12 @@ ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>>; /// Borrow the current thread's stack. - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>]; /// Mutably borrow the current thread's stack. - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec>; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operand.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operand.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operand.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operand.rs 2022-02-23 04:07:21.000000000 +0000 @@ -106,7 +106,7 @@ #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); -impl std::fmt::Display for ImmTy<'tcx, Tag> { +impl std::fmt::Display for ImmTy<'_, Tag> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Helper function for printing a scalar to a FmtPrinter fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>( @@ -512,7 +512,7 @@ self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, op.layout, )); Ok(op) @@ -534,7 +534,7 @@ Constant(ref constant) => { let val = - self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all // checked yet. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operator.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operator.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operator.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/operator.rs 2022-02-23 04:07:21.000000000 +0000 @@ -328,9 +328,10 @@ self.binary_int_op(bin_op, l, left.layout, r, right.layout) } _ if left.layout.ty.is_any_ptr() => { - // The RHS type must be the same *or an integer type* (for `Offset`). + // The RHS type must be a `pointer` *or an integer type* (for `Offset`). + // (Even when both sides are pointers, their type might differ, see issue #91636) assert!( - right.layout.ty == left.layout.ty || right.layout.ty.is_integral(), + right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", left.layout.ty, bin_op, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/place.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/place.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/place.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/place.rs 2022-02-23 04:07:21.000000000 +0000 @@ -150,7 +150,7 @@ } #[inline] - pub fn offset( + pub fn offset<'tcx>( self, offset: Size, meta: MemPlaceMeta, @@ -327,7 +327,7 @@ self.memory.get_mut(place.ptr, size, place.align) } - /// Check if this mplace is dereferencable and sufficiently aligned. + /// Check if this mplace is dereferenceable and sufficiently aligned. fn check_mplace_access( &self, mplace: MPlaceTy<'tcx, M::PointerTag>, @@ -362,21 +362,15 @@ // Re-use parent metadata to determine dynamic field layout. // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. - let align = match self.size_and_align_of(&base.meta, &field_layout)? { - Some((_, align)) => align, - None if offset == Size::ZERO => { - // An extern type at offset 0, we fall back to its static alignment. - // FIXME: Once we have made decisions for how to handle size and alignment - // of `extern type`, this should be adapted. It is just a temporary hack - // to get some code to work that probably ought to work. - field_layout.align.abi + match self.size_and_align_of(&base.meta, &field_layout)? { + Some((_, align)) => (base.meta, offset.align_to(align)), + None => { + // For unsized types with an extern type tail we perform no adjustments. + // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. + assert!(matches!(base.meta, MemPlaceMeta::None)); + (base.meta, offset) } - None => span_bug!( - self.cur_span(), - "cannot compute offset for extern type field at non-0 offset" - ), - }; - (base.meta, offset.align_to(align)) + } } else { // base.meta could be present; we might be accessing a sized field of an unsized // struct. @@ -420,7 +414,7 @@ // Iterates over all fields of an array. Much more efficient than doing the // same by repeatedly calling `mplace_array`. - pub(super) fn mplace_array_fields( + pub(super) fn mplace_array_fields<'a>( &self, base: &'a MPlaceTy<'tcx, Tag>, ) -> InterpResult<'tcx, impl Iterator>> + 'a> @@ -643,7 +637,7 @@ self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, place_ty.layout, )); Ok(place_ty) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/step.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/step.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/step.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/step.rs 2022-02-23 04:07:21.000000000 +0000 @@ -199,9 +199,9 @@ Aggregate(ref kind, ref operands) => { // active_field_index is for union initialization. let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { self.write_discriminant(variant_index, &dest)?; - if adt_def.is_enum() { + if self.tcx.adt_def(adt_did).is_enum() { assert!(active_field_index.is_none()); (self.place_downcast(&dest, variant_index)?, None) } else { @@ -242,11 +242,15 @@ let elem_size = first.layout.size; let first_ptr = first.ptr; let rest_ptr = first_ptr.offset(elem_size, self)?; + // For the alignment of `rest_ptr`, we crucially do *not* use `first.align` as + // that place might be more aligned than its type mandates (a `u8` array could + // be 4-aligned if it sits at the right spot in a struct). Instead we use + // `first.layout.align`, i.e., the alignment given by the type. self.memory.copy_repeatedly( first_ptr, first.align, rest_ptr, - first.align, + first.layout.align.abi, elem_size, length - 1, /*nonoverlapping:*/ true, @@ -267,12 +271,8 @@ self.write_immediate(place.to_ref(self), &dest)?; } - NullaryOp(mir::NullOp::Box, _) => { - M::box_alloc(self, &dest)?; - } - NullaryOp(null_op, ty) => { - let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); + let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; let layout = self.layout_of(ty)?; if layout.is_unsized() { // FIXME: This should be a span_bug (#80742) @@ -285,7 +285,6 @@ let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), - mir::NullOp::Box => unreachable!(), }; self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; } @@ -298,7 +297,8 @@ Cast(cast_kind, ref operand, cast_ty) => { let src = self.eval_operand(operand, None)?; - let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty); + let cast_ty = + self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?; self.cast(&src, cast_kind, cast_ty, &dest)?; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/terminator.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/terminator.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/terminator.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/terminator.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,14 +1,14 @@ use std::borrow::Cow; use std::convert::TryFrom; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::{self, LayoutOf as _, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::Instance; use rustc_middle::{ mir, ty::{self, Ty}, }; use rustc_target::abi; +use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; use super::{ @@ -17,10 +17,6 @@ }; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool { - layout::fn_can_unwind(*self.tcx, attrs, abi) - } - pub(super) fn eval_terminator( &mut self, terminator: &mir::Terminator<'tcx>, @@ -64,25 +60,27 @@ let old_stack = self.frame_idx(); let old_loc = self.frame().loc; let func = self.eval_operand(func, None)?; - let (fn_val, abi, caller_can_unwind) = match *func.layout.ty.kind() { - ty::FnPtr(sig) => { - let caller_abi = sig.abi(); + let args = self.eval_operands(args)?; + + let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); + let fn_sig = + self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); + let extra_args = &args[fn_sig.inputs().len()..]; + let extra_args = self.tcx.mk_type_list(extra_args.iter().map(|arg| arg.layout.ty)); + + let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() { + ty::FnPtr(_sig) => { let fn_ptr = self.read_pointer(&func)?; let fn_val = self.memory.get_fn(fn_ptr)?; - ( - fn_val, - caller_abi, - self.fn_can_unwind(CodegenFnAttrFlags::empty(), caller_abi), - ) + (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) } ty::FnDef(def_id, substs) => { - let sig = func.layout.ty.fn_sig(*self.tcx); + let instance = + self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?; ( - FnVal::Instance( - self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?, - ), - sig.abi(), - self.fn_can_unwind(self.tcx.codegen_fn_attrs(def_id).flags, sig.abi()), + FnVal::Instance(instance), + self.fn_abi_of_instance(instance, extra_args)?, + instance.def.requires_caller_location(*self.tcx), ) } _ => span_bug!( @@ -91,7 +89,7 @@ func.layout.ty ), }; - let args = self.eval_operands(args)?; + let dest_place; let ret = match destination { Some((dest, ret)) => { @@ -102,10 +100,11 @@ }; self.eval_fn_call( fn_val, - abi, - &args[..], + (fn_sig.abi, fn_abi), + &args, + with_caller_location, ret, - match (cleanup, caller_can_unwind) { + match (cleanup, fn_abi.can_unwind) { (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup), (None, true) => StackPopUnwind::Skip, (_, false) => StackPopUnwind::NotAllowed, @@ -174,68 +173,128 @@ } fn check_argument_compat( - rust_abi: bool, - caller: TyAndLayout<'tcx>, - callee: TyAndLayout<'tcx>, + caller_abi: &ArgAbi<'tcx, Ty<'tcx>>, + callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, ) -> bool { - if caller.ty == callee.ty { - // No question - return true; - } - if !rust_abi { - // Don't risk anything - return false; - } - // Compare layout - match (caller.abi, callee.abi) { - // Different valid ranges are okay (once we enforce validity, - // that will take care to make it UB to leave the range, just - // like for transmute). - (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value, - (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => { - caller1.value == callee1.value && caller2.value == callee2.value + // Heuristic for type comparison. + let layout_compat = || { + if caller_abi.layout.ty == callee_abi.layout.ty { + // No question + return true; + } + // Compare layout + match (caller_abi.layout.abi, callee_abi.layout.abi) { + // Different valid ranges are okay (once we enforce validity, + // that will take care to make it UB to leave the range, just + // like for transmute). + (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => { + caller.value == callee.value + } + ( + abi::Abi::ScalarPair(caller1, caller2), + abi::Abi::ScalarPair(callee1, callee2), + ) => caller1.value == callee1.value && caller2.value == callee2.value, + // Be conservative + _ => false, } - // Be conservative + }; + // Padding must be fully equal. + let pad_compat = || caller_abi.pad == callee_abi.pad; + // When comparing the PassMode, we have to be smart about comparing the attributes. + let arg_attr_compat = |a1: ArgAttributes, a2: ArgAttributes| { + // There's only one regular attribute that matters for the call ABI: InReg. + // Everything else is things like noalias, dereferencable, nonnull, ... + // (This also applies to pointee_size, pointee_align.) + if a1.regular.contains(ArgAttribute::InReg) != a2.regular.contains(ArgAttribute::InReg) + { + return false; + } + // We also compare the sign extension mode -- this could let the callee make assumptions + // about bits that conceptually were not even passed. + if a1.arg_ext != a2.arg_ext { + return false; + } + return true; + }; + let mode_compat = || match (caller_abi.mode, callee_abi.mode) { + (PassMode::Ignore, PassMode::Ignore) => true, + (PassMode::Direct(a1), PassMode::Direct(a2)) => arg_attr_compat(a1, a2), + (PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => { + arg_attr_compat(a1, a2) && arg_attr_compat(b1, b2) + } + (PassMode::Cast(c1), PassMode::Cast(c2)) => c1 == c2, + ( + PassMode::Indirect { attrs: a1, extra_attrs: None, on_stack: s1 }, + PassMode::Indirect { attrs: a2, extra_attrs: None, on_stack: s2 }, + ) => arg_attr_compat(a1, a2) && s1 == s2, + ( + PassMode::Indirect { attrs: a1, extra_attrs: Some(e1), on_stack: s1 }, + PassMode::Indirect { attrs: a2, extra_attrs: Some(e2), on_stack: s2 }, + ) => arg_attr_compat(a1, a2) && arg_attr_compat(e1, e2) && s1 == s2, _ => false, + }; + + if layout_compat() && pad_compat() && mode_compat() { + return true; } + trace!( + "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}", + caller_abi, + callee_abi + ); + return false; } - /// Pass a single argument, checking the types for compatibility. - fn pass_argument( + /// Initialize a single callee argument, checking the types for compatibility. + fn pass_argument<'x, 'y>( &mut self, - rust_abi: bool, - caller_arg: &mut impl Iterator>, + caller_args: &mut impl Iterator< + Item = (&'x OpTy<'tcx, M::PointerTag>, &'y ArgAbi<'tcx, Ty<'tcx>>), + >, + callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, callee_arg: &PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - if rust_abi && callee_arg.layout.is_zst() { - // Nothing to do. - trace!("Skipping callee ZST"); + ) -> InterpResult<'tcx> + where + 'tcx: 'x, + 'tcx: 'y, + { + if matches!(callee_abi.mode, PassMode::Ignore) { + // This one is skipped. return Ok(()); } - let caller_arg = caller_arg.next().ok_or_else(|| { + // Find next caller arg. + let (caller_arg, caller_abi) = caller_args.next().ok_or_else(|| { err_ub_format!("calling a function with fewer arguments than it requires") })?; - if rust_abi { - assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); - } // Now, check - if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { + if !Self::check_argument_compat(caller_abi, callee_abi) { throw_ub_format!( "calling a function with argument of type {:?} passing data of type {:?}", callee_arg.layout.ty, caller_arg.layout.ty ) } - // We allow some transmutes here + // We allow some transmutes here. + // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This + // is true for all `copy_op`, but there are a lot of special cases for argument passing + // specifically.) self.copy_op_transmute(&caller_arg, callee_arg) } /// Call this function -- pushing the stack frame and initializing the arguments. + /// + /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way. + /// However, we also need `caller_abi` to determine if we need to do untupling of arguments. + /// + /// `with_caller_location` indicates whether the caller passed a caller location. Miri + /// implements caller locations without argument passing, but to match `FnAbi` we need to know + /// when those arguments are present. pub(crate) fn eval_fn_call( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, - caller_abi: Abi, + (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), args: &[OpTy<'tcx, M::PointerTag>], + with_caller_location: bool, ret: Option<(&PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>, mut unwind: StackPopUnwind, ) -> InterpResult<'tcx> { @@ -248,39 +307,10 @@ } }; - let get_abi = |this: &Self, instance_ty: Ty<'tcx>| match instance_ty.kind() { - ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::Generator(..) => Abi::Rust, - _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty), - }; - - // ABI check - let check_abi = |callee_abi: Abi| -> InterpResult<'tcx> { - let normalize_abi = |abi| match abi { - Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic => - // These are all the same ABI, really. - { - Abi::Rust - } - abi => abi, - }; - if normalize_abi(caller_abi) != normalize_abi(callee_abi) { - throw_ub_format!( - "calling a function with ABI {} using caller ABI {}", - callee_abi.name(), - caller_abi.name() - ) - } - Ok(()) - }; - match instance.def { ty::InstanceDef::Intrinsic(..) => { - if M::enforce_abi(self) { - check_abi(get_abi(self, instance.ty(*self.tcx, self.param_env)))?; - } assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic); + // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic. M::call_intrinsic(self, instance, args, ret, unwind) } ty::InstanceDef::VtableShim(..) @@ -291,26 +321,37 @@ | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::Item(_) => { // We need MIR for this fn - let body = + let (body, instance) = match M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? { Some(body) => body, None => return Ok(()), }; - // Check against the ABI of the MIR body we are calling (not the ABI of `instance`; - // these can differ when `find_mir_or_eval_fn` does something clever like resolve - // exported symbol names). - let callee_def_id = body.source.def_id(); - let callee_abi = get_abi(self, self.tcx.type_of(callee_def_id)); + // Compute callee information using the `instance` returned by + // `find_mir_or_eval_fn`. + // FIXME: for variadic support, do we have to somehow determine calle's extra_args? + let callee_fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; + + if callee_fn_abi.c_variadic != caller_fn_abi.c_variadic { + throw_ub_format!( + "calling a c-variadic function via a non-variadic call site, or vice versa" + ); + } + if callee_fn_abi.c_variadic { + throw_unsup_format!("calling a c-variadic function is not supported"); + } if M::enforce_abi(self) { - check_abi(callee_abi)?; + if caller_fn_abi.conv != callee_fn_abi.conv { + throw_ub_format!( + "calling a function with calling convention {:?} using calling convention {:?}", + callee_fn_abi.conv, + caller_fn_abi.conv + ) + } } - if !matches!(unwind, StackPopUnwind::NotAllowed) - && !self - .fn_can_unwind(self.tcx.codegen_fn_attrs(callee_def_id).flags, callee_abi) - { + if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind { // The callee cannot unwind. unwind = StackPopUnwind::NotAllowed; } @@ -343,12 +384,8 @@ .collect::>() ); - // Figure out how to pass which arguments. - // The Rust ABI is special: ZST get skipped. - let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall); - - // We have two iterators: Where the arguments come from, - // and where they go to. + // In principle, we have two iterators: Where the arguments come from, and where + // they go to. // For where they come from: If the ABI is RustCall, we untuple the // last incoming argument. These two iterators do not have the same type, @@ -373,53 +410,59 @@ // Plain arg passing Cow::from(args) }; - // Skip ZSTs - let mut caller_iter = - caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied(); + // If `with_caller_location` is set we pretend there is an extra argument (that + // we will not pass). + assert_eq!( + caller_args.len() + if with_caller_location { 1 } else { 0 }, + caller_fn_abi.args.len(), + "mismatch between caller ABI and caller arguments", + ); + let mut caller_args = caller_args + .iter() + .zip(caller_fn_abi.args.iter()) + .filter(|arg_and_abi| !matches!(arg_and_abi.1.mode, PassMode::Ignore)); // Now we have to spread them out across the callee's locals, // taking into account the `spread_arg`. If we could write // this is a single iterator (that handles `spread_arg`), then // `pass_argument` would be the loop body. It takes care to // not advance `caller_iter` for ZSTs. + let mut callee_args_abis = callee_fn_abi.args.iter(); for local in body.args_iter() { let dest = self.eval_place(mir::Place::from(local))?; if Some(local) == body.spread_arg { // Must be a tuple for i in 0..dest.layout.fields.count() { let dest = self.place_field(&dest, i)?; - self.pass_argument(rust_abi, &mut caller_iter, &dest)?; + let callee_abi = callee_args_abis.next().unwrap(); + self.pass_argument(&mut caller_args, callee_abi, &dest)?; } } else { // Normal argument - self.pass_argument(rust_abi, &mut caller_iter, &dest)?; + let callee_abi = callee_args_abis.next().unwrap(); + self.pass_argument(&mut caller_args, callee_abi, &dest)?; } } - // Now we should have no more caller args - if caller_iter.next().is_some() { + // If the callee needs a caller location, pretend we consume one more argument from the ABI. + if instance.def.requires_caller_location(*self.tcx) { + callee_args_abis.next().unwrap(); + } + // Now we should have no more caller args or callee arg ABIs + assert!( + callee_args_abis.next().is_none(), + "mismatch between callee ABI and callee body arguments" + ); + if caller_args.next().is_some() { throw_ub_format!("calling a function with more arguments than it expected") } // Don't forget to check the return type! - if let Some((caller_ret, _)) = ret { - let callee_ret = self.eval_place(mir::Place::return_place())?; - if !Self::check_argument_compat( - rust_abi, - caller_ret.layout, - callee_ret.layout, - ) { - throw_ub_format!( - "calling a function with return type {:?} passing \ - return place of type {:?}", - callee_ret.layout.ty, - caller_ret.layout.ty - ) - } - } else { - let local = mir::RETURN_PLACE; - let callee_layout = self.layout_of_local(self.frame(), local, None)?; - if !callee_layout.abi.is_uninhabited() { - throw_ub_format!("calling a returning function without a return place") - } + if !Self::check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret) { + throw_ub_format!( + "calling a function with return type {:?} passing \ + return place of type {:?}", + callee_fn_abi.ret.layout.ty, + caller_fn_abi.ret.layout.ty, + ) } }; match res { @@ -464,7 +507,14 @@ )); trace!("Patched self operand to {:#?}", args[0]); // recurse with concrete function - self.eval_fn_call(fn_val, caller_abi, &args, ret, unwind) + self.eval_fn_call( + fn_val, + (caller_abi, caller_fn_abi), + &args, + with_caller_location, + ret, + unwind, + ) } } } @@ -489,6 +539,7 @@ } _ => (instance, place), }; + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; let arg = ImmTy::from_immediate( place.to_ref(self), @@ -500,8 +551,9 @@ self.eval_fn_call( FnVal::Instance(instance), - Abi::Rust, + (Abi::Rust, fn_abi), &[arg.into()], + false, Some((&dest.into(), target)), match unwind { Some(cleanup) => StackPopUnwind::Cleanup(cleanup), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/validity.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/validity.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/validity.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/interpret/validity.rs 2022-02-23 04:07:21.000000000 +0000 @@ -14,6 +14,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use std::hash::Hash; @@ -736,9 +737,15 @@ #[inline(always)] fn visit_union( &mut self, - _op: &OpTy<'tcx, M::PointerTag>, + op: &OpTy<'tcx, M::PointerTag>, _fields: NonZeroUsize, ) -> InterpResult<'tcx> { + // Special check preventing `UnsafeCell` inside unions in the inner part of constants. + if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) { + if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) { + throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" }); + } + } Ok(()) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,8 +11,6 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/check.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/check.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/check.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/check.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,8 +1,8 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. use rustc_errors::{Applicability, Diagnostic, ErrorReported}; +use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, LangItem}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; @@ -14,8 +14,7 @@ use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; -use rustc_trait_selection::traits::error_reporting::InferCtxtExt; -use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine}; +use rustc_trait_selection::traits::SelectionContext; use std::mem; use std::ops::Deref; @@ -36,7 +35,7 @@ needs_non_const_drop: Option>, } -impl Qualifs<'mir, 'tcx> { +impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { /// Returns `true` if `local` is `NeedsDrop` at the given `Location`. /// /// Only updates the cursor if absolutely necessary @@ -186,7 +185,7 @@ secondary_errors: Vec, } -impl Deref for Checker<'mir, 'tcx> { +impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { @@ -194,7 +193,7 @@ } } -impl Checker<'mir, 'tcx> { +impl<'mir, 'tcx> Checker<'mir, 'tcx> { pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self { Checker { span: ccx.body.span, @@ -255,16 +254,6 @@ self.visit_body(&body); } - // Ensure that the end result is `Sync` in a non-thread local `static`. - let should_check_for_sync = self.const_kind() - == hir::ConstContext::Static(hir::Mutability::Not) - && !tcx.is_thread_local_static(def_id.to_def_id()); - - if should_check_for_sync { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - check_return_ty_is_sync(tcx, &body, hir_id); - } - // If we got through const-checking without emitting any "primary" errors, emit any // "secondary" errors if they occurred. let secondary_errors = mem::take(&mut self.secondary_errors); @@ -284,7 +273,7 @@ struct StorageDeads { locals: BitSet, } - impl Visitor<'tcx> for StorageDeads { + impl<'tcx> Visitor<'tcx> for StorageDeads { fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) { if let StatementKind::StorageDead(l) = stmt.kind { self.locals.insert(l); @@ -471,7 +460,7 @@ } } -impl Visitor<'tcx> for Checker<'mir, 'tcx> { +impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) { trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup); @@ -643,7 +632,6 @@ } Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} - Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, ref operand) => { @@ -812,7 +800,7 @@ if let Some(trait_id) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); if !self.tcx.features().const_trait_impl { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(Some((callee, substs)))); return; } @@ -828,8 +816,7 @@ ); let implsrc = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = - SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); @@ -868,7 +855,7 @@ } if !nonconst_call_permission { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(None)); return; } } @@ -937,7 +924,7 @@ } if !nonconst_call_permission { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(None)); return; } } @@ -1054,21 +1041,7 @@ } } -fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) { - let ty = body.return_ty(); - tcx.infer_ctxt().enter(|infcx| { - let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); - let mut fulfillment_cx = traits::FulfillmentContext::new(); - let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span)); - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause); - let errors = fulfillment_cx.select_all_or_error(&infcx); - if !errors.is_empty() { - infcx.report_fulfillment_errors(&errors, None, false); - } - }); -} - -fn place_as_reborrow( +fn place_as_reborrow<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, place: Place<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -28,7 +28,7 @@ pub const_kind: Option, } -impl ConstCx<'mir, 'tcx> { +impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { let def_id = body.source.def_id().expect_local(); let param_env = tcx.param_env(def_id); @@ -72,11 +72,7 @@ } } -pub fn rustc_allow_const_fn_unstable( - tcx: TyCtxt<'tcx>, - def_id: DefId, - feature_gate: Symbol, -) -> bool { +pub fn rustc_allow_const_fn_unstable(tcx: TyCtxt<'_>, def_id: DefId, feature_gate: Symbol) -> bool { let attrs = tcx.get_attrs(def_id); attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) } @@ -89,7 +85,7 @@ // functions can be called in a const-context by users of the stable compiler. "const-stable" // functions are subject to more stringent restrictions than "const-unstable" functions: They // cannot use unstable features and can only call other "const-stable" functions. -pub fn is_const_stable_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { +pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { use attr::{ConstStability, Stability, StabilityLevel}; // A default body marked const is not const-stable because const diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/ops.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/ops.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/ops.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/ops.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,12 +1,14 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::mir; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::{mir, ty::AssocKind}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol::Ident, Span, Symbol}; +use rustc_span::{BytePos, Pos}; use super::ConstCx; @@ -37,7 +39,7 @@ DiagnosticImportance::Primary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; } #[derive(Debug)] @@ -51,7 +53,7 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_floating_point_arithmetic, @@ -65,24 +67,78 @@ #[derive(Debug)] pub struct FnCallIndirect; impl NonConstOp for FnCallIndirect { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn") } } /// A function call where the callee is not marked as `const`. #[derive(Debug)] -pub struct FnCallNonConst; -impl NonConstOp for FnCallNonConst { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - struct_span_err!( +pub struct FnCallNonConst<'tcx>(pub Option<(DefId, SubstsRef<'tcx>)>); +impl<'a> NonConstOp for FnCallNonConst<'a> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = struct_span_err!( ccx.tcx.sess, span, E0015, "calls in {}s are limited to constant functions, \ tuple structs and tuple variants", ccx.const_kind(), - ) + ); + + if let FnCallNonConst(Some((callee, substs))) = *self { + if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() { + if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind( + ccx.tcx, + Ident::with_dummy_span(sym::eq), + AssocKind::Fn, + trait_def_id, + ) { + if callee == eq_item.def_id && substs.len() == 2 { + match (substs[0].unpack(), substs[1].unpack()) { + (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty)) + if self_ty == rhs_ty + && self_ty.is_ref() + && self_ty.peel_refs().is_primitive() => + { + let mut num_refs = 0; + let mut tmp_ty = self_ty; + while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() { + num_refs += 1; + tmp_ty = inner_ty; + } + let deref = "*".repeat(num_refs); + + if let Ok(call_str) = + ccx.tcx.sess.source_map().span_to_snippet(span) + { + if let Some(eq_idx) = call_str.find("==") { + if let Some(rhs_idx) = call_str[(eq_idx + 2)..] + .find(|c: char| !c.is_whitespace()) + { + let rhs_pos = span.lo() + + BytePos::from_usize(eq_idx + 2 + rhs_idx); + let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos); + err.multipart_suggestion( + "consider dereferencing here", + vec![ + (span.shrink_to_lo(), deref.clone()), + (rhs_span, deref), + ], + Applicability::MachineApplicable, + ); + } + } + } + } + _ => {} + } + } + } + } + } + + err } } @@ -93,7 +149,7 @@ pub struct FnCallUnstable(pub DefId, pub Option); impl NonConstOp for FnCallUnstable { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let FnCallUnstable(def_id, feature) = *self; let mut err = ccx.tcx.sess.struct_span_err( @@ -127,7 +183,7 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_fn_ptr_basics, @@ -148,7 +204,7 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind()); if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg) @@ -161,7 +217,7 @@ #[derive(Debug)] pub struct HeapAllocation; impl NonConstOp for HeapAllocation { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -185,7 +241,7 @@ #[derive(Debug)] pub struct InlineAsm; impl NonConstOp for InlineAsm { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, span, @@ -201,7 +257,7 @@ pub dropped_at: Option, } impl NonConstOp for LiveDrop { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -229,7 +285,7 @@ // not additionally emit a feature gate error if activating the feature gate won't work. DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_refs_to_cell, @@ -245,7 +301,7 @@ /// it in the future for static items. pub struct CellBorrow; impl NonConstOp for CellBorrow { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -292,7 +348,7 @@ DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let raw = match self.0 { hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Ref => "", @@ -331,7 +387,7 @@ Status::Unstable(sym::const_mut_refs) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let raw = match self.0 { hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Ref => "", @@ -358,7 +414,7 @@ DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -372,7 +428,7 @@ #[derive(Debug)] pub struct PanicNonStr; impl NonConstOp for PanicNonStr { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.struct_span_err( span, "argument to `panic!()` in a const context must have type `&str`", @@ -386,7 +442,7 @@ #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = ccx .tcx .sess @@ -406,7 +462,7 @@ Status::Unstable(sym::const_mut_refs) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -422,7 +478,7 @@ #[derive(Debug)] pub struct RawPtrToIntCast; impl NonConstOp for RawPtrToIntCast { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = ccx .tcx .sess @@ -447,7 +503,7 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -473,7 +529,7 @@ #[derive(Debug)] pub struct ThreadLocalAccess; impl NonConstOp for ThreadLocalAccess { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, span, @@ -504,7 +560,11 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -534,7 +594,11 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_fn_ptr_basics, @@ -551,7 +615,11 @@ Status::Unstable(sym::const_impl_trait) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_impl_trait, @@ -581,7 +649,11 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, @@ -620,7 +692,11 @@ } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, @@ -647,7 +723,11 @@ Status::Unstable(sym::const_trait_bound_opt_out) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_trait_bound_opt_out, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ /// /// This is separate from the rest of the const checking logic because it must run after drop /// elaboration. -pub fn check_live_drops(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { +pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { let def_id = body.source.def_id().expect_local(); let const_kind = tcx.hir().body_const_context(def_id); if const_kind.is_none() { @@ -50,7 +50,7 @@ } // So we can access `body` and `tcx`. -impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { +impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { @@ -58,13 +58,13 @@ } } -impl CheckLiveDrops<'mir, 'tcx> { +impl CheckLiveDrops<'_, '_> { fn check_live_drop(&self, span: Span) { ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit(); } } -impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { +impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) { trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup); @@ -80,7 +80,8 @@ trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } + | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to @@ -104,11 +105,6 @@ } } - mir::TerminatorKind::DropAndReplace { .. } => span_bug!( - terminator.source_info.span, - "`DropAndReplace` should be removed by drop elaboration", - ), - mir::TerminatorKind::Abort | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,6 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorReported; -use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; @@ -14,7 +13,7 @@ use super::ConstCx; -pub fn in_any_value_of_ty( +pub fn in_any_value_of_ty<'tcx>( cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>, error_occured: Option, @@ -59,7 +58,7 @@ /// from a call to another function. /// /// It also determines the `Qualif`s for primitive types. - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; /// Returns `true` if this `Qualif` is inherent to the given struct or enum. /// @@ -69,7 +68,7 @@ /// with a custom `Drop` impl is inherently `NeedsDrop`. /// /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound. - fn in_adt_inherently( + fn in_adt_inherently<'tcx>( cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, substs: SubstsRef<'tcx>, @@ -90,11 +89,15 @@ qualifs.has_mut_interior } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently. // It arises structurally for all other types. Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type() @@ -116,11 +119,15 @@ qualifs.needs_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { ty.needs_drop(cx.tcx, cx.param_env) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { adt.has_dtor(cx.tcx) } } @@ -138,7 +145,7 @@ qualifs.needs_non_const_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { // Avoid selecting for simple cases. match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() { Ok([]) => return false, @@ -167,7 +174,7 @@ ); let implsrc = cx.tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); !matches!( @@ -178,7 +185,11 @@ ) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { adt.has_non_const_dtor(cx.tcx) } } @@ -193,7 +204,7 @@ qualifs.custom_eq } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, // we know that at least some values of that type are not structural-match. I say "some" // because that component may be part of an enum variant (e.g., @@ -203,7 +214,7 @@ traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some() } - fn in_adt_inherently( + fn in_adt_inherently<'tcx>( cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, substs: SubstsRef<'tcx>, @@ -216,7 +227,11 @@ // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. /// Returns `true` if this `Rvalue` contains qualif `Q`. -pub fn in_rvalue(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool +pub fn in_rvalue<'tcx, Q, F>( + cx: &ConstCx<'_, 'tcx>, + in_local: &mut F, + rvalue: &Rvalue<'tcx>, +) -> bool where Q: Qualif, F: FnMut(Local) -> bool, @@ -255,7 +270,8 @@ Rvalue::Aggregate(kind, operands) => { // Return early if we know that the struct or enum being constructed is always // qualified. - if let AggregateKind::Adt(def, _, substs, ..) = **kind { + if let AggregateKind::Adt(adt_did, _, substs, ..) = **kind { + let def = cx.tcx.adt_def(adt_did); if Q::in_adt_inherently(cx, def, substs) { return true; } @@ -271,7 +287,7 @@ } /// Returns `true` if this `Place` contains qualif `Q`. -pub fn in_place(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool +pub fn in_place<'tcx, Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool where Q: Qualif, F: FnMut(Local) -> bool, @@ -303,7 +319,11 @@ } /// Returns `true` if this `Operand` contains qualif `Q`. -pub fn in_operand(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool +pub fn in_operand<'tcx, Q, F>( + cx: &ConstCx<'_, 'tcx>, + in_local: &mut F, + operand: &Operand<'tcx>, +) -> bool where Q: Qualif, F: FnMut(Local) -> bool, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,7 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::JoinSemiLattice; +use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces}; use rustc_span::DUMMY_SP; use std::fmt; @@ -27,7 +28,7 @@ _qualif: PhantomData, } -impl TransferFunction<'a, 'mir, 'tcx, Q> +impl<'a, 'mir, 'tcx, Q> TransferFunction<'a, 'mir, 'tcx, Q> where Q: Qualif, { @@ -80,18 +81,18 @@ fn apply_call_return_effect( &mut self, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - // We cannot reason about another function's internals, so use conservative type-based - // qualification for the result of a function call. - let return_ty = return_place.ty(self.ccx.body, self.ccx.tcx).ty; - let qualif = Q::in_any_value_of_ty(self.ccx, return_ty); + return_places.for_each(|place| { + // We cannot reason about another function's internals, so use conservative type-based + // qualification for the result of a function call. + let return_ty = place.ty(self.ccx.body, self.ccx.tcx).ty; + let qualif = Q::in_any_value_of_ty(self.ccx, return_ty); - if !return_place.is_indirect() { - self.assign_qualif_direct(&return_place, qualif); - } + if !place.is_indirect() { + self.assign_qualif_direct(&place, qualif); + } + }); } fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool { @@ -126,7 +127,7 @@ } } -impl Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q> +impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -329,7 +330,7 @@ } } -impl rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -349,7 +350,7 @@ } } -impl rustc_mir_dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -375,10 +376,8 @@ &self, state: &mut Self::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - self.transfer_function(state).apply_call_return_effect(block, func, args, return_place) + self.transfer_function(state).apply_call_return_effect(block, return_places) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,3 @@ pub mod check_consts; pub mod promote_consts; pub mod validate; - -pub use rustc_middle::mir::MirPass; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/promote_consts.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/promote_consts.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/promote_consts.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/promote_consts.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,7 +27,6 @@ use std::{cmp, iter, mem}; use crate::transform::check_consts::{qualifs, ConstCx}; -use crate::transform::MirPass; /// A `MirPass` for promotion. /// @@ -42,6 +41,10 @@ } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { + fn phase_change(&self) -> Option { + Some(MirPhase::ConstPromotion) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // @@ -165,8 +168,8 @@ } } -pub fn collect_temps_and_candidates( - ccx: &ConstCx<'mir, 'tcx>, +pub fn collect_temps_and_candidates<'tcx>( + ccx: &ConstCx<'_, 'tcx>, rpo: &mut ReversePostorder<'_, 'tcx>, ) -> (IndexVec, Vec) { let mut collector = Collector { @@ -188,7 +191,7 @@ temps: &'a IndexVec, } -impl std::ops::Deref for Validator<'a, 'tcx> { +impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> { type Target = ConstCx<'a, 'tcx>; fn deref(&self) -> &Self::Target { @@ -505,7 +508,6 @@ } Rvalue::NullaryOp(op, _) => match op { - NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} NullOp::AlignOf => {} }, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/validate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/validate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/validate.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/transform/validate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,14 +1,13 @@ //! Validates the MIR to ensure that invariants are upheld. -use super::MirPass; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, - PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, + AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand, + PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; @@ -67,7 +66,7 @@ /// /// The point of this function is to approximate "equal up to subtyping". However, /// the approximation is incorrect as variance is ignored. -pub fn equal_up_to_regions( +pub fn equal_up_to_regions<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, src: Ty<'tcx>, @@ -496,10 +495,13 @@ self.check_edge(location, *unwind, EdgeKind::Unwind); } } - TerminatorKind::InlineAsm { destination, .. } => { + TerminatorKind::InlineAsm { destination, cleanup, .. } => { if let Some(destination) = destination { self.check_edge(location, *destination, EdgeKind::Normal); } + if let Some(cleanup) = cleanup { + self.check_edge(location, *cleanup, EdgeKind::Unwind); + } } // Nothing to validate for these. TerminatorKind::Resume diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/util/aggregate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/util/aggregate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/util/aggregate.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_const_eval/src/util/aggregate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -22,7 +22,8 @@ ) -> impl Iterator> + TrustedLen { let mut set_discriminant = None; let active_field_index = match kind { - AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { + let adt_def = tcx.adt_def(adt_did); if adt_def.is_enum() { set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { place: Box::new(lhs), variant_index }, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/binary_search_util/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/binary_search_util/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/binary_search_util/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/binary_search_util/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ /// function finds the range of elements that match the key. `data` /// must have been sorted as if by a call to `sort_by_key` for this to /// work. -pub fn binary_search_slice(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E] +pub fn binary_search_slice<'d, E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E] where K: Ord, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/fingerprint.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/fingerprint.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/fingerprint.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/fingerprint.rs 2022-02-23 04:07:21.000000000 +0000 @@ -142,7 +142,7 @@ impl Encodable for Fingerprint { #[inline] fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_raw_bytes(&self.to_le_bytes()[..])?; + s.emit_raw_bytes(&self.to_le_bytes())?; Ok(()) } } @@ -151,7 +151,7 @@ #[inline] fn decode(d: &mut D) -> Result { let mut bytes = [0u8; 16]; - d.read_raw_bytes_into(&mut bytes[..])?; + d.read_raw_bytes_into(&mut bytes)?; Ok(Fingerprint::from_le_bytes(bytes)) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/functor.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/functor.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/functor.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/functor.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,35 +1,32 @@ use rustc_index::vec::{Idx, IndexVec}; use std::mem; -use std::ptr; -pub trait IdFunctor { +pub trait IdFunctor: Sized { type Inner; - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner; + F: FnMut(Self::Inner) -> Result; } impl IdFunctor for Box { type Inner = T; #[inline] - fn map_id(self, mut f: F) -> Self + fn try_map_id(self, mut f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { let raw = Box::into_raw(self); - unsafe { + Ok(unsafe { // SAFETY: The raw pointer points to a valid value of type `T`. - let value = ptr::read(raw); + let value = raw.read(); // SAFETY: Converts `Box` to `Box>` which is the // inverse of `Box::assume_init()` and should be safe. - let mut raw: Box> = Box::from_raw(raw.cast()); + let raw: Box> = Box::from_raw(raw.cast()); // SAFETY: Write the mapped value back into the `Box`. - raw.write(f(value)); - // SAFETY: We just initialized `raw`. - raw.assume_init() - } + Box::write(raw, f(value)?) + }) } } @@ -37,23 +34,43 @@ type Inner = T; #[inline] - fn map_id(mut self, mut f: F) -> Self + fn try_map_id(self, mut f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - // FIXME: We don't really care about panics here and leak - // far more than we should, but that should be fine for now. - let len = self.len(); + struct HoleVec { + vec: Vec>, + hole: Option, + } + + impl Drop for HoleVec { + fn drop(&mut self) { + unsafe { + for (index, slot) in self.vec.iter_mut().enumerate() { + if self.hole != Some(index) { + mem::ManuallyDrop::drop(slot); + } + } + } + } + } + unsafe { - self.set_len(0); - let start = self.as_mut_ptr(); - for i in 0..len { - let p = start.add(i); - ptr::write(p, f(ptr::read(p))); + let (ptr, length, capacity) = self.into_raw_parts(); + let vec = Vec::from_raw_parts(ptr.cast(), length, capacity); + let mut hole_vec = HoleVec { vec, hole: None }; + + for (index, slot) in hole_vec.vec.iter_mut().enumerate() { + hole_vec.hole = Some(index); + let original = mem::ManuallyDrop::take(slot); + let mapped = f(original)?; + *slot = mem::ManuallyDrop::new(mapped); + hole_vec.hole = None; } - self.set_len(len); + + mem::forget(hole_vec); + Ok(Vec::from_raw_parts(ptr, length, capacity)) } - self } } @@ -61,11 +78,11 @@ type Inner = T; #[inline] - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - Vec::from(self).map_id(f).into() + Vec::from(self).try_map_id(f).map(Into::into) } } @@ -73,10 +90,10 @@ type Inner = T; #[inline] - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - IndexVec::from_raw(self.raw.map_id(f)) + self.raw.try_map_id(f).map(IndexVec::from_raw) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,11 +1,14 @@ //! Finding the dominators in a control-flow graph. //! -//! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy, -//! "A Simple, Fast Dominance Algorithm", -//! Rice Computer Science TS-06-33870, -//! . +//! Algorithm based on Loukas Georgiadis, +//! "Linear-Time Algorithms for Dominators and Related Problems", +//! +//! +//! Additionally useful is the original Lengauer-Tarjan paper on this subject, +//! "A Fast Algorithm for Finding Dominators in a Flowgraph" +//! Thomas Lengauer and Robert Endre Tarjan. +//! -use super::iterate::reverse_post_order; use super::ControlFlowGraph; use rustc_index::vec::{Idx, IndexVec}; use std::cmp::Ordering; @@ -13,69 +16,239 @@ #[cfg(test)] mod tests; -pub fn dominators(graph: G) -> Dominators { - let start_node = graph.start_node(); - let rpo = reverse_post_order(&graph, start_node); - dominators_given_rpo(graph, &rpo) +struct PreOrderFrame { + pre_order_idx: PreorderIndex, + iter: Iter, } -fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Dominators { - let start_node = graph.start_node(); - assert_eq!(rpo[0], start_node); +rustc_index::newtype_index! { + struct PreorderIndex { .. } +} +pub fn dominators(graph: G) -> Dominators { // compute the post order index (rank) for each node let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes()); - for (index, node) in rpo.iter().rev().cloned().enumerate() { - post_order_rank[node] = index; - } - let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes()); - immediate_dominators[start_node] = Some(start_node); + // We allocate capacity for the full set of nodes, because most of the time + // most of the nodes *are* reachable. + let mut parent: IndexVec = + IndexVec::with_capacity(graph.num_nodes()); + + let mut stack = vec![PreOrderFrame { + pre_order_idx: PreorderIndex::new(0), + iter: graph.successors(graph.start_node()), + }]; + let mut pre_order_to_real: IndexVec = + IndexVec::with_capacity(graph.num_nodes()); + let mut real_to_pre_order: IndexVec> = + IndexVec::from_elem_n(None, graph.num_nodes()); + pre_order_to_real.push(graph.start_node()); + parent.push(PreorderIndex::new(0)); // the parent of the root node is the root for now. + real_to_pre_order[graph.start_node()] = Some(PreorderIndex::new(0)); + let mut post_order_idx = 0; + + // Traverse the graph, collecting a number of things: + // + // * Preorder mapping (to it, and back to the actual ordering) + // * Postorder mapping (used exclusively for rank_partial_cmp on the final product) + // * Parents for each vertex in the preorder tree + // + // These are all done here rather than through one of the 'standard' + // graph traversals to help make this fast. + 'recurse: while let Some(frame) = stack.last_mut() { + while let Some(successor) = frame.iter.next() { + if real_to_pre_order[successor].is_none() { + let pre_order_idx = pre_order_to_real.push(successor); + real_to_pre_order[successor] = Some(pre_order_idx); + parent.push(frame.pre_order_idx); + stack.push(PreOrderFrame { pre_order_idx, iter: graph.successors(successor) }); - let mut changed = true; - while changed { - changed = false; - - for &node in &rpo[1..] { - let mut new_idom = None; - for pred in graph.predecessors(node) { - if immediate_dominators[pred].is_some() { - // (*) dominators for `pred` have been calculated - new_idom = Some(if let Some(new_idom) = new_idom { - intersect(&post_order_rank, &immediate_dominators, new_idom, pred) - } else { - pred - }); - } + continue 'recurse; } + } + post_order_rank[pre_order_to_real[frame.pre_order_idx]] = post_order_idx; + post_order_idx += 1; - if new_idom != immediate_dominators[node] { - immediate_dominators[node] = new_idom; - changed = true; - } + stack.pop(); + } + + let reachable_vertices = pre_order_to_real.len(); + + let mut idom = IndexVec::from_elem_n(PreorderIndex::new(0), reachable_vertices); + let mut semi = IndexVec::from_fn_n(std::convert::identity, reachable_vertices); + let mut label = semi.clone(); + let mut bucket = IndexVec::from_elem_n(vec![], reachable_vertices); + let mut lastlinked = None; + + // We loop over vertices in reverse preorder. This implements the pseudocode + // of the simple Lengauer-Tarjan algorithm. A few key facts are noted here + // which are helpful for understanding the code (full proofs and such are + // found in various papers, including one cited at the top of this file). + // + // For each vertex w (which is not the root), + // * semi[w] is a proper ancestor of the vertex w (i.e., semi[w] != w) + // * idom[w] is an ancestor of semi[w] (i.e., idom[w] may equal semi[w]) + // + // An immediate dominator of w (idom[w]) is a vertex v where v dominates w + // and every other dominator of w dominates v. (Every vertex except the root has + // a unique immediate dominator.) + // + // A semidominator for a given vertex w (semi[w]) is the vertex v with minimum + // preorder number such that there exists a path from v to w in which all elements (other than w) have + // preorder numbers greater than w (i.e., this path is not the tree path to + // w). + for w in (PreorderIndex::new(1)..PreorderIndex::new(reachable_vertices)).rev() { + // Optimization: process buckets just once, at the start of the + // iteration. Do not explicitly empty the bucket (even though it will + // not be used again), to save some instructions. + // + // The bucket here contains the vertices whose semidominator is the + // vertex w, which we are guaranteed to have found: all vertices who can + // be semidominated by w must have a preorder number exceeding w, so + // they have been placed in the bucket. + // + // We compute a partial set of immediate dominators here. + let z = parent[w]; + for &v in bucket[z].iter() { + // This uses the result of Lemma 5 from section 2 from the original + // 1979 paper, to compute either the immediate or relative dominator + // for a given vertex v. + // + // eval returns a vertex y, for which semi[y] is minimum among + // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the + // z bucket. + // + // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v]. + // If semi[y] = semi[v], though, idom[v] = semi[v]. + // + // Using this, we can either set idom[v] to be: + // * semi[v] (i.e. z), if semi[y] is z + // * idom[y], otherwise + // + // We don't directly set to idom[y] though as it's not necessarily + // known yet. The second preorder traversal will cleanup by updating + // the idom for any that were missed in this pass. + let y = eval(&mut parent, lastlinked, &semi, &mut label, v); + idom[v] = if semi[y] < z { y } else { z }; + } + + // This loop computes the semi[w] for w. + semi[w] = w; + for v in graph.predecessors(pre_order_to_real[w]) { + let v = real_to_pre_order[v].unwrap(); + + // eval returns a vertex x from which semi[x] is minimum among + // vertices semi[v] +> x *> v. + // + // From Lemma 4 from section 2, we know that the semidominator of a + // vertex w is the minimum (by preorder number) vertex of the + // following: + // + // * direct predecessors of w with preorder number less than w + // * semidominators of u such that u > w and there exists (v, w) + // such that u *> v + // + // This loop therefore identifies such a minima. Note that any + // semidominator path to w must have all but the first vertex go + // through vertices numbered greater than w, so the reverse preorder + // traversal we are using guarantees that all of the information we + // might need is available at this point. + // + // The eval call will give us semi[x], which is either: + // + // * v itself, if v has not yet been processed + // * A possible 'best' semidominator for w. + let x = eval(&mut parent, lastlinked, &semi, &mut label, v); + semi[w] = std::cmp::min(semi[w], semi[x]); + } + // semi[w] is now semidominator(w) and won't change any more. + + // Optimization: Do not insert into buckets if parent[w] = semi[w], as + // we then immediately know the idom. + // + // If we don't yet know the idom directly, then push this vertex into + // our semidominator's bucket, where it will get processed at a later + // stage to compute its immediate dominator. + if parent[w] != semi[w] { + bucket[semi[w]].push(w); + } else { + idom[w] = parent[w]; } + + // Optimization: We share the parent array between processed and not + // processed elements; lastlinked represents the divider. + lastlinked = Some(w); + } + + // Finalize the idoms for any that were not fully settable during initial + // traversal. + // + // If idom[w] != semi[w] then we know that we've stored vertex y from above + // into idom[w]. It is known to be our 'relative dominator', which means + // that it's one of w's ancestors and has the same immediate dominator as w, + // so use that idom. + for w in PreorderIndex::new(1)..PreorderIndex::new(reachable_vertices) { + if idom[w] != semi[w] { + idom[w] = idom[idom[w]]; + } + } + + let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes()); + for (idx, node) in pre_order_to_real.iter_enumerated() { + immediate_dominators[*node] = Some(pre_order_to_real[idom[idx]]); } Dominators { post_order_rank, immediate_dominators } } -fn intersect( - post_order_rank: &IndexVec, - immediate_dominators: &IndexVec>, - mut node1: Node, - mut node2: Node, -) -> Node { - while node1 != node2 { - while post_order_rank[node1] < post_order_rank[node2] { - node1 = immediate_dominators[node1].unwrap(); - } +/// Evaluate the link-eval virtual forest, providing the currently minimum semi +/// value for the passed `node` (which may be itself). +/// +/// This maintains that for every vertex v, `label[v]` is such that: +/// +/// ```text +/// semi[eval(v)] = min { semi[label[u]] | root_in_forest(v) +> u *> v } +/// ``` +/// +/// where `+>` is a proper ancestor and `*>` is just an ancestor. +#[inline] +fn eval( + ancestor: &mut IndexVec, + lastlinked: Option, + semi: &IndexVec, + label: &mut IndexVec, + node: PreorderIndex, +) -> PreorderIndex { + if is_processed(node, lastlinked) { + compress(ancestor, lastlinked, semi, label, node); + label[node] + } else { + node + } +} - while post_order_rank[node2] < post_order_rank[node1] { - node2 = immediate_dominators[node2].unwrap(); +#[inline] +fn is_processed(v: PreorderIndex, lastlinked: Option) -> bool { + if let Some(ll) = lastlinked { v >= ll } else { false } +} + +#[inline] +fn compress( + ancestor: &mut IndexVec, + lastlinked: Option, + semi: &IndexVec, + label: &mut IndexVec, + v: PreorderIndex, +) { + assert!(is_processed(v, lastlinked)); + let u = ancestor[v]; + if is_processed(u, lastlinked) { + compress(ancestor, lastlinked, semi, label, u); + if semi[label[u]] < semi[label[v]] { + label[v] = label[u]; } + ancestor[v] = ancestor[u]; } - - node1 } #[derive(Clone, Debug)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/dominators/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -32,3 +32,14 @@ assert_eq!(immediate_dominators[5], Some(6)); assert_eq!(immediate_dominators[6], Some(6)); } + +#[test] +fn paper_slt() { + // example from the paper: + let graph = TestGraph::new( + 1, + &[(1, 2), (1, 3), (2, 3), (2, 7), (3, 4), (3, 6), (4, 5), (5, 4), (6, 7), (7, 8), (8, 5)], + ); + + dominators(&graph); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/iterate/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/iterate/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/iterate/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/iterate/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -79,7 +79,7 @@ visited: BitSet, } -impl DepthFirstSearch<'graph, G> +impl<'graph, G> DepthFirstSearch<'graph, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, { @@ -209,7 +209,7 @@ settled: BitSet, } -impl TriColorDepthFirstSearch<'graph, G> +impl<'graph, G> TriColorDepthFirstSearch<'graph, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, { @@ -276,7 +276,7 @@ } } -impl TriColorDepthFirstSearch<'graph, G> +impl TriColorDepthFirstSearch<'_, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors + WithStartNode, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/scc/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/scc/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/scc/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/scc/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,6 +9,7 @@ use crate::graph::vec_graph::VecGraph; use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; +use std::cmp::Ord; use std::ops::Range; #[cfg(test)] @@ -38,7 +39,7 @@ all_successors: Vec, } -impl Sccs { +impl Sccs { pub fn new(graph: &(impl DirectedGraph + WithNumNodes + WithSuccessors)) -> Self { SccsConstruction::construct(graph) } @@ -85,7 +86,7 @@ type Node = S; } -impl WithNumNodes for Sccs { +impl WithNumNodes for Sccs { fn num_nodes(&self) -> usize { self.num_sccs() } @@ -97,13 +98,13 @@ } } -impl GraphSuccessors<'graph> for Sccs { +impl<'graph, N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs { type Item = S; type Iter = std::iter::Cloned>; } -impl WithSuccessors for Sccs { +impl WithSuccessors for Sccs { fn successors(&self, node: S) -> >::Iter { self.successors(node).iter().cloned() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,5 @@ +use std::cmp::Ord; + use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; @@ -17,7 +19,7 @@ edge_targets: Vec, } -impl VecGraph { +impl VecGraph { pub fn new(num_nodes: usize, mut edge_pairs: Vec<(N, N)>) -> Self { // Sort the edges by the source -- this is important. edge_pairs.sort(); @@ -94,13 +96,13 @@ } } -impl GraphSuccessors<'graph> for VecGraph { +impl<'graph, N: Idx> GraphSuccessors<'graph> for VecGraph { type Item = N; type Iter = std::iter::Cloned>; } -impl WithSuccessors for VecGraph { +impl WithSuccessors for VecGraph { fn successors(&self, node: N) -> >::Iter { self.successors(node).iter().cloned() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -15,16 +15,15 @@ #![feature(core_intrinsics)] #![feature(extend_one)] #![feature(hash_raw_entry)] -#![feature(in_band_lifetimes)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(never_type)] #![feature(type_alias_impl_trait)] #![feature(new_uninit)] -#![feature(nll)] #![feature(once_cell)] #![feature(test)] #![feature(thread_id_value)] +#![feature(vec_into_raw_parts)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/profiling.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/profiling.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/profiling.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/profiling.rs 2022-02-23 04:07:21.000000000 +0000 @@ -649,7 +649,7 @@ fn drop(&mut self) { if let Some((start_time, start_rss, ref message)) = self.start_and_message { let end_rss = get_resident_set_size(); - print_time_passes_entry(&message[..], start_time.elapsed(), start_rss, end_rss); + print_time_passes_entry(&message, start_time.elapsed(), start_rss, end_rss); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/small_c_str.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/small_c_str.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/small_c_str.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/small_c_str.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,7 +46,7 @@ #[inline] pub fn as_c_str(&self) -> &ffi::CStr { - unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) } + unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data) } } #[inline] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sorted_map/index_map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sorted_map/index_map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sorted_map/index_map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sorted_map/index_map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -84,7 +84,7 @@ /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. #[inline] - pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { + pub fn get_by_key(&self, key: K) -> impl Iterator + '_ { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -94,7 +94,7 @@ /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. #[inline] - pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator { + pub fn get_by_key_enumerated(&self, key: K) -> impl Iterator + '_ { let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key); self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| { let (k, v) = &self.items[i]; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -423,14 +423,14 @@ /// adapts Item of array reference iterator to Item of hashmap reference iterator. #[inline(always)] -fn adapt_array_ref_it(pair: &'a (K, V)) -> (&'a K, &'a V) { +fn adapt_array_ref_it(pair: &(K, V)) -> (&K, &V) { let (a, b) = pair; (a, b) } /// adapts Item of array mut reference iterator to Item of hashmap mut reference iterator. #[inline(always)] -fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { +fn adapt_array_mut_it(pair: &mut (K, V)) -> (&K, &mut V) { let (a, b) = pair; (a, b) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/set.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/set.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/set.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/sso/set.rs 2022-02-23 04:07:21.000000000 +0000 @@ -75,7 +75,7 @@ /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. #[inline] - pub fn iter(&'a self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.into_iter() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -71,3 +71,30 @@ assert_eq!(h.finalize(), expected); } + +fn hash>(t: &T) -> u128 { + let mut h = StableHasher::new(); + let ctx = &mut (); + t.hash_stable(ctx, &mut h); + h.finish() +} + +// Check that bit set hash includes the domain size. +#[test] +fn test_hash_bit_set() { + use rustc_index::bit_set::BitSet; + let a: BitSet = BitSet::new_empty(1); + let b: BitSet = BitSet::new_empty(2); + assert_ne!(a, b); + assert_ne!(hash(&a), hash(&b)); +} + +// Check that bit matrix hash includes the matrix dimensions. +#[test] +fn test_hash_bit_matrix() { + use rustc_index::bit_set::BitMatrix; + let a: BitMatrix = BitMatrix::new(1, 1); + let b: BitMatrix = BitMatrix::new(1, 2); + assert_ne!(a, b); + assert_ne!(hash(&a), hash(&b)); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/stable_hasher.rs 2022-02-23 04:07:21.000000000 +0000 @@ -42,6 +42,7 @@ } impl StableHasherResult for u128 { + #[inline] fn finish(hasher: StableHasher) -> Self { let (_0, _1) = hasher.finalize(); u128::from(_0) | (u128::from(_1) << 64) @@ -49,6 +50,7 @@ } impl StableHasherResult for u64 { + #[inline] fn finish(hasher: StableHasher) -> Self { hasher.finalize().0 } @@ -377,9 +379,8 @@ impl HashStable for str { #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { - self.len().hash(hasher); - self.as_bytes().hash(hasher); + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.as_bytes().hash_stable(ctx, hasher); } } @@ -476,14 +477,14 @@ } impl HashStable for bit_set::BitSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); + fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); } } impl HashStable for bit_set::BitMatrix { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); + fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); } } @@ -507,7 +508,11 @@ { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); } } @@ -517,9 +522,10 @@ R: BuildHasher, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + }); } } @@ -529,10 +535,11 @@ V: HashStable, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut entries: Vec<_> = - self.iter().map(|(k, v)| (k.to_stable_hash_key(hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); } } @@ -541,25 +548,38 @@ K: ToStableHashKey, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + }); } } -pub fn hash_stable_hashmap( +fn stable_hash_reduce( hcx: &mut HCX, hasher: &mut StableHasher, - map: &::std::collections::HashMap, - to_stable_hash_key: F, + mut collection: C, + length: usize, + hash_function: F, ) where - K: Eq, - V: HashStable, - R: BuildHasher, - SK: HashStable + Ord, - F: Fn(&K, &HCX) -> SK, + C: Iterator, + F: Fn(&mut StableHasher, &mut HCX, I), { - let mut entries: Vec<_> = map.iter().map(|(k, v)| (to_stable_hash_key(k, hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); + length.hash_stable(hcx, hasher); + + match length { + 1 => { + hash_function(hasher, hcx, collection.next().unwrap()); + } + _ => { + let hash = collection + .map(|value| { + let mut hasher = StableHasher::new(); + hash_function(&mut hasher, hcx, value); + hasher.finish::() + }) + .reduce(|accum, value| accum.wrapping_add(value)); + hash.hash_stable(hcx, hasher); + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/tagged_ptr/copy.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/tagged_ptr/copy.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/tagged_ptr/copy.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/tagged_ptr/copy.rs 2022-02-23 04:07:21.000000000 +0000 @@ -94,9 +94,11 @@ // SAFETY: pointer_raw returns the original pointer unsafe { std::mem::transmute_copy(&self.pointer_raw()) } } + #[inline] pub fn tag(&self) -> T { unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) } } + #[inline] pub fn set_tag(&mut self, tag: T) { let mut packed = self.packed.get(); let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/thin_vec.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/thin_vec.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/thin_vec.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/thin_vec.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,7 +5,7 @@ /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. -#[derive(Clone, Encodable, Decodable, Debug)] +#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq)] pub struct ThinVec(Option>>); impl ThinVec { @@ -20,6 +20,13 @@ pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { self.into_iter() } + + pub fn push(&mut self, item: T) { + match *self { + ThinVec(Some(ref mut vec)) => vec.push(item), + ThinVec(None) => *self = vec![item].into(), + } + } } impl From> for ThinVec { @@ -101,10 +108,7 @@ } fn extend_one(&mut self, item: T) { - match *self { - ThinVec(Some(ref mut vec)) => vec.push(item), - ThinVec(None) => *self = vec![item].into(), - } + self.push(item) } fn extend_reserve(&mut self, additional: usize) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/vec_linked_list.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/vec_linked_list.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/vec_linked_list.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_data_structures/src/vec_linked_list.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,8 +2,8 @@ pub fn iter( first: Option, - links: &'a Ls, -) -> impl Iterator + 'a + links: &Ls, +) -> impl Iterator + '_ where Ls: Links, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_driver/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_driver/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_driver/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_driver/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -8,10 +8,8 @@ [dependencies] libc = "0.2" -atty = "0.2" tracing = { version = "0.1.28" } -tracing-subscriber = { version = "0.2.16", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } -tracing-tree = "0.1.9" +rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_target = { path = "../rustc_target" } @@ -40,4 +38,4 @@ [features] llvm = ['rustc_interface/llvm'] -max_level_info = ['tracing/max_level_info'] +max_level_info = ['rustc_log/max_level_info'] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_driver/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_driver/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_driver/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_driver/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -24,6 +24,7 @@ use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; +use rustc_log::stdout_isatty; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -514,14 +515,6 @@ #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -fn stdout_isatty() -> bool { - atty::is(atty::Stream::Stdout) -} - -fn stderr_isatty() -> bool { - atty::is(atty::Stream::Stderr) -} - fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { @@ -872,7 +865,7 @@ let print_lints = |lints: Vec<&Lint>| { for lint in lints { - let name = lint.name_lower().replace("_", "-"); + let name = lint.name_lower().replace('_', "-"); println!( " {} {:7.7} {}", padded(&name), @@ -908,10 +901,10 @@ let print_lint_groups = |lints: Vec<(&'static str, Vec)>| { for (name, to) in lints { - let name = name.to_lowercase().replace("_", "-"); + let name = name.to_lowercase().replace('_', "-"); let desc = to .into_iter() - .map(|x| x.to_string().replace("_", "-")) + .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); println!(" {} {}", padded(&name), desc); @@ -960,7 +953,7 @@ println!( " {} {:>width$}=val -- {}", cmdline_opt, - name.replace("_", "-"), + name.replace('_', "-"), desc, width = max_len ); @@ -1015,7 +1008,7 @@ .iter() .map(|&(name, ..)| ('C', name)) .chain(DB_OPTIONS.iter().map(|&(name, ..)| ('Z', name))) - .find(|&(_, name)| *opt == name.replace("_", "-")) + .find(|&(_, name)| *opt == name.replace('_', "-")) .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)), _ => None, }; @@ -1047,7 +1040,7 @@ let wall = matches.opt_strs("W"); if wall.iter().any(|x| *x == "all") { print_wall_help(); - return None; + rustc_errors::FatalError.raise(); } // Don't handle -W help here, because we might first load plugins. @@ -1254,54 +1247,18 @@ /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG") + if let Err(error) = rustc_log::init_rustc_env_logger() { + early_error(ErrorOutputType::default(), &error.to_string()); + } } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - use tracing_subscriber::{ - filter::{self, EnvFilter, LevelFilter}, - layer::SubscriberExt, - }; - - let filter = match std::env::var(env) { - Ok(env) => EnvFilter::new(env), - _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), - }; - - let color_logs = match std::env::var(String::from(env) + "_COLOR") { - Ok(value) => match value.as_ref() { - "always" => true, - "never" => false, - "auto" => stderr_isatty(), - _ => early_error( - ErrorOutputType::default(), - &format!( - "invalid log color value '{}': expected one of always, never, or auto", - value - ), - ), - }, - Err(std::env::VarError::NotPresent) => stderr_isatty(), - Err(std::env::VarError::NotUnicode(_value)) => early_error( - ErrorOutputType::default(), - "non-Unicode log color value: expected one of always, never, or auto", - ), - }; - - let layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr) - .with_indent_lines(true) - .with_ansi(color_logs) - .with_targets(true) - .with_indent_amount(2); - #[cfg(parallel_compiler)] - let layer = layer.with_thread_ids(true).with_thread_names(true); - - let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + if let Err(error) = rustc_log::init_env_logger(env) { + early_error(ErrorOutputType::default(), &error.to_string()); + } } #[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0038.md rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0038.md --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0038.md 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0038.md 2022-02-23 04:07:21.000000000 +0000 @@ -1,34 +1,64 @@ -Trait objects like `Box` can only be constructed when certain -requirements are satisfied by the trait in question. - -Trait objects are a form of dynamic dispatch and use a dynamically sized type -for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a -type, as in `Box`, the inner type is 'unsized'. In such cases the boxed -pointer is a 'fat pointer' that contains an extra pointer to a table of methods -(among other things) for dynamic dispatch. This design mandates some -restrictions on the types of traits that are allowed to be used in trait -objects, which are collectively termed as 'object safety' rules. - -Attempting to create a trait object for a non object-safe trait will trigger -this error. - -There are various rules: - -### The trait cannot require `Self: Sized` - -When `Trait` is treated as a type, the type does not implement the special -`Sized` trait, because the type does not have a known size at compile time and -can only be accessed behind a pointer. Thus, if we have a trait like the -following: +For any given trait `Trait` there may be a related _type_ called the _trait +object type_ which is typically written as `dyn Trait`. In earlier editions of +Rust, trait object types were written as plain `Trait` (just the name of the +trait, written in type positions) but this was a bit too confusing, so we now +write `dyn Trait`. + +Some traits are not allowed to be used as trait object types. The traits that +are allowed to be used as trait object types are called "object-safe" traits. +Attempting to use a trait object type for a trait that is not object-safe will +trigger error E0038. + +Two general aspects of trait object types give rise to the restrictions: + + 1. Trait object types are dynamically sized types (DSTs), and trait objects of + these types can only be accessed through pointers, such as `&dyn Trait` or + `Box`. The size of such a pointer is known, but the size of the + `dyn Trait` object pointed-to by the pointer is _opaque_ to code working + with it, and different tait objects with the same trait object type may + have different sizes. + + 2. The pointer used to access a trait object is paired with an extra pointer + to a "virtual method table" or "vtable", which is used to implement dynamic + dispatch to the object's implementations of the trait's methods. There is a + single such vtable for each trait implementation, but different trait + objects with the same trait object type may point to vtables from different + implementations. + +The specific conditions that violate object-safety follow, most of which relate +to missing size information and vtable polymorphism arising from these aspects. + +### The trait requires `Self: Sized` + +Traits that are declared as `Trait: Sized` or which otherwise inherit a +constraint of `Self:Sized` are not object-safe. + +The reasoning behind this is somewhat subtle. It derives from the fact that Rust +requires (and defines) that every trait object type `dyn Trait` automatically +implements `Trait`. Rust does this to simplify error reporting and ease +interoperation between static and dynamic polymorphism. For example, this code +works: ``` -trait Foo where Self: Sized { +trait Trait { +} + +fn static_foo(b: &T) { +} +fn dynamic_bar(a: &dyn Trait) { + static_foo(a) } ``` -We cannot create an object of type `Box` or `&Foo` since in this case -`Self` would not be `Sized`. +This code works because `dyn Trait`, if it exists, always implements `Trait`. + +However as we know, any `dyn Trait` is also unsized, and so it can never +implement a sized trait like `Trait:Sized`. So, rather than allow an exception +to the rule that `dyn Trait` always implements `Trait`, Rust chooses to prohibit +such a `dyn Trait` from existing at all. + +Only unsized traits are considered object-safe. Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing @@ -67,7 +97,7 @@ fn foo(&self) -> Self; } -fn call_foo(x: Box) { +fn call_foo(x: Box) { let y = x.foo(); // What type is y? // ... } @@ -76,7 +106,8 @@ If only some methods aren't object-safe, you can add a `where Self: Sized` bound on them to mark them as explicitly unavailable to trait objects. The functionality will still be available to all other implementers, including -`Box` which is itself sized (assuming you `impl Trait for Box`). +`Box` which is itself sized (assuming you `impl Trait for Box`). ``` trait Trait { @@ -115,7 +146,9 @@ ``` At compile time each implementation of `Trait` will produce a table containing -the various methods (and other items) related to the implementation. +the various methods (and other items) related to the implementation, which will +be used as the virtual method table for a `dyn Trait` object derived from that +implementation. This works fine, but when the method gains generic parameters, we can have a problem. @@ -174,7 +207,7 @@ # impl Trait for u8 { fn foo(&self, on: T) {} } # impl Trait for bool { fn foo(&self, on: T) {} } # // etc. -fn call_foo(thing: Box) { +fn call_foo(thing: Box) { thing.foo(true); // this could be any one of the 8 types above thing.foo(1); thing.foo("hello"); @@ -200,7 +233,7 @@ ``` If this is not an option, consider replacing the type parameter with another -trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the +trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the number of types you intend to feed to this method is limited, consider manually listing out the methods of different types. @@ -226,7 +259,7 @@ } ``` -### The trait cannot contain associated constants +### Trait contains associated constants Just like static functions, associated constants aren't stored on the method table. If the trait or any subtrait contain an associated constant, they cannot @@ -248,7 +281,7 @@ } ``` -### The trait cannot use `Self` as a type parameter in the supertrait listing +### Trait uses `Self` as a type parameter in the supertrait listing This is similar to the second sub-error, but subtler. It happens in situations like the following: diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0227.md rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0227.md --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0227.md 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes/E0227.md 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,33 @@ +This error indicates that the compiler is unable to determine whether there is +exactly one unique region in the set of derived region bounds. + +Example of erroneous code: + +```compile_fail,E0227 +trait Foo<'foo>: 'foo {} +trait Bar<'bar>: 'bar {} + +trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} + +struct Baz<'foo, 'bar> { + baz: dyn FooBar<'foo, 'bar>, +} +``` + +Here, `baz` can have either `'foo` or `'bar` lifetimes. + +To resolve this error, provide an explicit lifetime: + +```rust +trait Foo<'foo>: 'foo {} +trait Bar<'bar>: 'bar {} + +trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} + +struct Baz<'foo, 'bar, 'baz> +where + 'baz: 'foo + 'bar, +{ + obj: dyn FooBar<'foo, 'bar> + 'baz, +} +``` diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_error_codes/src/error_codes.rs 2022-02-23 04:07:21.000000000 +0000 @@ -120,6 +120,7 @@ E0224: include_str!("./error_codes/E0224.md"), E0225: include_str!("./error_codes/E0225.md"), E0226: include_str!("./error_codes/E0226.md"), +E0227: include_str!("./error_codes/E0227.md"), E0228: include_str!("./error_codes/E0228.md"), E0229: include_str!("./error_codes/E0229.md"), E0230: include_str!("./error_codes/E0230.md"), @@ -530,7 +531,6 @@ // E0217, // ambiguous associated type, defined in multiple supertraits // E0218, // no associated type defined // E0219, // associated type defined in higher-ranked supertrait - E0227, // ambiguous lifetime bound, explicit lifetime bound required // E0233, // E0234, // E0235, // structure constructor specifies a structure of type but diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/emitter.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/emitter.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/emitter.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/emitter.rs 2022-02-23 04:07:21.000000000 +0000 @@ -214,7 +214,7 @@ /// Formats the substitutions of the primary_span /// - /// The are a lot of conditions to this method, but in short: + /// There are a lot of conditions to this method, but in short: /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the @@ -736,7 +736,9 @@ let line_offset = buffer.num_lines(); - let left = margin.left(source_string.len()); // Left trim + // Left trim + let left = margin.left(source_string.len()); + // Account for unicode characters of width !=0 that were removed. let left = source_string .chars() @@ -1623,18 +1625,27 @@ suggestions.iter().take(MAX_SUGGESTIONS) { notice_capitalization |= only_capitalization; - // Only show underline if the suggestion spans a single line and doesn't cover the - // entirety of the code output. If you have multiple replacements in the same line - // of code, show the underline. - let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim()) - && complete.lines().count() == 1; let has_deletion = parts.iter().any(|p| p.is_deletion()); let is_multiline = complete.lines().count() > 1; - let show_diff = has_deletion && !is_multiline; + enum DisplaySuggestion { + Underline, + Diff, + None, + } + + let show_code_change = if has_deletion && !is_multiline { + DisplaySuggestion::Diff + } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim()) + && !is_multiline + { + DisplaySuggestion::Underline + } else { + DisplaySuggestion::None + }; - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { row_num += 1; } @@ -1657,7 +1668,7 @@ &self.maybe_anonymized(line_start + line_pos), Style::LineNumber, ); - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Add the line number for both addition and removal to drive the point home. // // N - fn foo(bar: A) { @@ -1727,7 +1738,7 @@ let mut offsets: Vec<(usize, isize)> = Vec::new(); // Only show an underline in the suggestions if the suggestion is not the // entirety of the code being shown and the displayed code is not multiline. - if show_underline { + if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change { draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); for part in parts { let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; @@ -1755,7 +1766,7 @@ assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - if !show_diff { + if let DisplaySuggestion::Underline = show_code_change { // If this is a replacement, underline with `^`, if this is an addition // underline with `+`. buffer.putc( @@ -1766,7 +1777,7 @@ ); } } - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Colorize removal with red in diff format. buffer.set_style_range( row_num - 2, @@ -1797,7 +1808,7 @@ // if we elided some lines, add an ellipsis if lines.next().is_some() { buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); - } else if !show_underline { + } else if let DisplaySuggestion::None = show_code_change { draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); row_num += 1; } @@ -2083,7 +2094,7 @@ ('\t', " "), // We do our own tab replacement ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently - ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk + ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always. ('\u{202E}', ""), ('\u{2066}', ""), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_errors/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,8 +6,6 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(let_else)] #![feature(nll)] @@ -1013,7 +1011,9 @@ } fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get()) + self.flags + .treat_err_as_bug + .map_or(false, |c| self.err_count() + self.lint_err_count >= c.get()) } fn print_error_count(&mut self, registry: &Registry) { @@ -1205,7 +1205,10 @@ fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { - match (self.err_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0)) { + match ( + self.err_count() + self.lint_err_count, + self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0), + ) { (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), (0, _) | (1, _) => {} (count, as_bug) => panic!( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/base.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -48,6 +48,7 @@ Param(ast::Param), FieldDef(ast::FieldDef), Variant(ast::Variant), + Crate(ast::Crate), } impl Annotatable { @@ -66,6 +67,7 @@ Annotatable::Param(ref p) => p.span, Annotatable::FieldDef(ref sf) => sf.span, Annotatable::Variant(ref v) => v.span, + Annotatable::Crate(ref c) => c.span, } } @@ -84,6 +86,7 @@ Annotatable::Param(p) => p.visit_attrs(f), Annotatable::FieldDef(sf) => sf.visit_attrs(f), Annotatable::Variant(v) => v.visit_attrs(f), + Annotatable::Crate(c) => c.visit_attrs(f), } } @@ -102,6 +105,7 @@ Annotatable::Param(p) => visitor.visit_param(p), Annotatable::FieldDef(sf) => visitor.visit_field_def(sf), Annotatable::Variant(v) => visitor.visit_variant(v), + Annotatable::Crate(c) => visitor.visit_crate(c), } } @@ -122,7 +126,8 @@ | Annotatable::GenericParam(..) | Annotatable::Param(..) | Annotatable::FieldDef(..) - | Annotatable::Variant(..) => panic!("unexpected annotatable"), + | Annotatable::Variant(..) + | Annotatable::Crate(..) => panic!("unexpected annotatable"), } } @@ -220,6 +225,13 @@ _ => panic!("expected variant"), } } + + pub fn expect_crate(self) -> ast::Crate { + match self { + Annotatable::Crate(krate) => krate, + _ => panic!("expected krate"), + } + } } /// Result of an expansion that may need to be retried. @@ -419,6 +431,11 @@ fn make_variants(self: Box) -> Option> { None } + + fn make_crate(self: Box) -> Option { + // Fn-like macros cannot produce a crate. + unreachable!() + } } macro_rules! make_MacEager { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/config.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/config.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/config.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/config.rs 2022-02-23 04:07:21.000000000 +0000 @@ -171,7 +171,7 @@ } if let Some(allowed) = sess.opts.debugging_opts.allow_features.as_ref() { - if allowed.iter().all(|f| name.as_str() != *f) { + if allowed.iter().all(|f| name.as_str() != f) { struct_span_err!( span_handler, mi.span(), @@ -402,7 +402,24 @@ ); trees.push((bracket_group, Spacing::Alone)); let tokens = Some(LazyTokenStream::new(AttrAnnotatedTokenStream::new(trees))); - self.process_cfg_attr(attr::mk_attr_from_item(item, tokens, attr.style, span)) + let attr = attr::mk_attr_from_item(item, tokens, attr.style, span); + if attr.has_name(sym::crate_type) { + self.sess.parse_sess.buffer_lint( + rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + attr.span, + ast::CRATE_NODE_ID, + "`crate_type` within an `#![cfg_attr] attribute is deprecated`", + ); + } + if attr.has_name(sym::crate_name) { + self.sess.parse_sess.buffer_lint( + rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + attr.span, + ast::CRATE_NODE_ID, + "`crate_name` within an `#![cfg_attr] attribute is deprecated`", + ); + } + self.process_cfg_attr(attr) }) .collect() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/expand.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/expand.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/expand.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/expand.rs 2022-02-23 04:07:21.000000000 +0000 @@ -14,13 +14,13 @@ use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; -use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; +use rustc_ast::{NodeId, PatKind, Path, StmtKind}; use rustc_ast_pretty::pprust; use rustc_attr::is_builtin_attr; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, FatalError, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_feature::Features; use rustc_parse::parser::{ AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma, @@ -33,7 +33,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{FileName, LocalExpnId, Span}; -use smallvec::{smallvec, SmallVec}; +use smallvec::SmallVec; use std::ops::DerefMut; use std::path::PathBuf; use std::rc::Rc; @@ -205,6 +205,7 @@ Variants(SmallVec<[ast::Variant; 1]>) { "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants; } + Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; } } pub enum SupportsMacroExpansion { @@ -227,9 +228,8 @@ AstFragmentKind::Items | AstFragmentKind::TraitItems | AstFragmentKind::ImplItems - | AstFragmentKind::ForeignItems => { - SupportsMacroExpansion::Yes { supports_inner_attrs: true } - } + | AstFragmentKind::ForeignItems + | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true }, AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats @@ -288,6 +288,9 @@ AstFragmentKind::OptExpr => { AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)) } + AstFragmentKind::Crate => { + AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate()) + } AstFragmentKind::Pat | AstFragmentKind::Ty => { panic!("patterns and types aren't annotatable") } @@ -359,9 +362,7 @@ MacroExpander { cx, monotonic } } - // FIXME: Avoid visiting the crate as a `Mod` item, - // make crate a first class expansion target instead. - pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { + pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate { let file_path = match self.cx.source_map().span_to_filename(krate.span) { FileName::Real(name) => name .into_local_path() @@ -375,52 +376,8 @@ file_path_stack: vec![file_path], dir_path, }); - - let krate_item = AstFragment::Items(smallvec![P(ast::Item { - attrs: krate.attrs, - span: krate.span, - kind: ast::ItemKind::Mod( - Unsafe::No, - ModKind::Loaded(krate.items, Inline::Yes, krate.span) - ), - ident: Ident::empty(), - id: ast::DUMMY_NODE_ID, - vis: ast::Visibility { - span: krate.span.shrink_to_lo(), - kind: ast::VisibilityKind::Public, - tokens: None, - }, - tokens: None, - })]); - - match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { - Some(ast::Item { - attrs, - kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)), - .. - }) => { - krate.attrs = attrs; - krate.items = items; - } - None => { - // Resolution failed so we return an empty expansion - krate.attrs = vec![]; - krate.items = vec![]; - } - Some(ast::Item { span, kind, .. }) => { - krate.attrs = vec![]; - krate.items = vec![]; - self.cx.span_err( - span, - &format!( - "expected crate top-level item to be a module after macro expansion, found {} {}", - kind.article(), kind.descr() - ), - ); - // FIXME: this workaround issue #84569 - FatalError.raise(); - } - }; + let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate(); + assert_eq!(krate.id, ast::CRATE_NODE_ID); self.cx.trace_macros_diag(); krate } @@ -708,26 +665,32 @@ SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - let mut fake_tokens = false; - if let Annotatable::Item(item_inner) = &item { - if let ItemKind::Mod(_, mod_kind) = &item_inner.kind { - // FIXME: Collect tokens and use them instead of generating - // fake ones. These are unstable, so it needs to be - // fixed prior to stabilization - // Fake tokens when we are invoking an inner attribute, and: - fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) && - // We are invoking an attribute on the crate root, or an outline - // module - (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _))); - } - } - let tokens = if fake_tokens { - rustc_parse::fake_token_stream( + let tokens = match &item { + // FIXME: Collect tokens and use them instead of generating + // fake ones. These are unstable, so it needs to be + // fixed prior to stabilization + // Fake tokens when we are invoking an inner attribute, and + // we are invoking it on an out-of-line module or crate. + Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate( &self.cx.sess.parse_sess, - &item.into_nonterminal(), - ) - } else { - item.into_tokens(&self.cx.sess.parse_sess) + krate, + ), + Annotatable::Item(item_inner) + if matches!(attr.style, ast::AttrStyle::Inner) + && matches!( + item_inner.kind, + ItemKind::Mod( + _, + ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _), + ) + ) => + { + rustc_parse::fake_token_stream( + &self.cx.sess.parse_sess, + &item.into_nonterminal(), + ) + } + _ => item.into_tokens(&self.cx.sess.parse_sess), }; let attr_item = attr.unwrap_normal_item(); if let MacArgs::Eq(..) = attr_item.args { @@ -804,7 +767,8 @@ Annotatable::Item(_) | Annotatable::TraitItem(_) | Annotatable::ImplItem(_) - | Annotatable::ForeignItem(_) => return, + | Annotatable::ForeignItem(_) + | Annotatable::Crate(..) => return, Annotatable::Stmt(stmt) => { // Attributes are stable on item statements, // but unstable on all other kinds of statements @@ -949,6 +913,7 @@ RecoverComma::No, RecoverColon::Yes, )?), + AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?), AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats @@ -1195,6 +1160,33 @@ } impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { + fn visit_crate(&mut self, krate: &mut ast::Crate) { + visit_clobber(krate, |krate| { + let span = krate.span; + let mut krate = match self.configure(krate) { + Some(krate) => krate, + None => { + return ast::Crate { + attrs: Vec::new(), + items: Vec::new(), + span, + id: self.cx.resolver.next_node_id(), + is_placeholder: false, + }; + } + }; + + if let Some(attr) = self.take_first_attr(&mut krate) { + return self + .collect_attr(attr, Annotatable::Crate(krate), AstFragmentKind::Crate) + .make_crate(); + } + + assign_id!(self, &mut krate.id, || noop_visit_crate(&mut krate, self)); + krate + }) + } + fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); visit_clobber(expr.deref_mut(), |mut expr| { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,9 +1,7 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] -#![feature(destructuring_assignment)] -#![cfg_attr(bootstrap, feature(format_args_capture))] +#![cfg_attr(bootstrap, feature(destructuring_assignment))] #![feature(if_let_guard)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_parser.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_parser.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_parser.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_parser.rs 2022-02-23 04:07:21.000000000 +0000 @@ -584,9 +584,7 @@ // // At the beginning of the loop, if we reach the end of the delimited submatcher, // we pop the stack to backtrack out of the descent. - seq - @ - (TokenTree::Delimited(..) + seq @ (TokenTree::Delimited(..) | TokenTree::Token(Token { kind: DocComment(..), .. })) => { let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); let idx = item.idx; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_rules.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_rules.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_rules.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/macro_rules.rs 2022-02-23 04:07:21.000000000 +0000 @@ -253,7 +253,7 @@ for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { - mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts, _ => cx.span_bug(sp, "malformed macro lhs"), }; @@ -353,7 +353,7 @@ for lhs in lhses { // try each arm's matchers let lhs_tt = match *lhs { - mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts, _ => continue, }; if let Success(_) = @@ -677,11 +677,11 @@ first.replace_with(tt.clone()); } TokenTree::Delimited(span, ref delimited) => { - build_recur(sets, &delimited.tts[..]); + build_recur(sets, &delimited.tts); first.replace_with(delimited.open_tt(span)); } TokenTree::Sequence(sp, ref seq_rep) => { - let subfirst = build_recur(sets, &seq_rep.tts[..]); + let subfirst = build_recur(sets, &seq_rep.tts); match sets.first.entry(sp.entire()) { Entry::Vacant(vac) => { @@ -748,7 +748,7 @@ let subfirst = match self.first.get(&sp.entire()) { Some(&Some(ref subfirst)) => subfirst, Some(&None) => { - subfirst_owned = self.first(&seq_rep.tts[..]); + subfirst_owned = self.first(&seq_rep.tts); &subfirst_owned } None => { @@ -1027,6 +1027,24 @@ ), ); err.span_label(sp, format!("not allowed after `{}` fragments", kind)); + + if kind == NonterminalKind::PatWithOr + && sess.edition == Edition::Edition2021 + && next_token.is_token(&BinOp(token::BinOpToken::Or)) + { + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + span, + name, + Some(NonterminalKind::PatParam { inferred: false }), + )); + err.span_suggestion( + span, + &format!("try a `pat_param` fragment specifier instead"), + suggestion, + Applicability::MaybeIncorrect, + ); + } + let msg = "allowed there are: "; match possible { &[] => {} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/transcribe.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/transcribe.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/transcribe.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/mbe/transcribe.rs 2022-02-23 04:07:21.000000000 +0000 @@ -175,12 +175,12 @@ )); } - LockstepIterSize::Contradiction(ref msg) => { + LockstepIterSize::Contradiction(msg) => { // FIXME: this really ought to be caught at macro definition time... It // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - return Err(cx.struct_span_err(seq.span(), &msg[..])); + return Err(cx.struct_span_err(seq.span(), &msg)); } LockstepIterSize::Constraint(len, _) => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/module.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/module.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/module.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/module.rs 2022-02-23 04:07:21.000000000 +0000 @@ -103,10 +103,10 @@ if let DirOwnership::Owned { relative } = &mut dir_ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - dir_path.push(&*ident.as_str()); + dir_path.push(ident.as_str()); } } - dir_path.push(&*ident.as_str()); + dir_path.push(ident.as_str()); (dir_path, dir_ownership) } @@ -170,8 +170,8 @@ ) -> Option { // Extract path string from first `#[path = "path_string"]` attribute. let first_path = attrs.iter().find(|at| at.has_name(sym::path))?; - let path_string = match first_path.value_str() { - Some(s) => s.as_str(), + let path_sym = match first_path.value_str() { + Some(s) => s, None => { // This check is here mainly to catch attempting to use a macro, // such as #[path = concat!(...)]. This isn't currently supported @@ -189,14 +189,16 @@ } }; + let path_str = path_sym.as_str(); + // On windows, the base path might have the form // `\\?\foo\bar` in which case it does not tolerate // mixed `/` and `\` separators, so canonicalize // `/` to `\`. #[cfg(windows)] - let path_string = path_string.replace("/", "\\"); + let path_str = path_str.replace("/", "\\"); - Some(dir_path.join(&*path_string)) + Some(dir_path.join(path_str)) } /// Returns a path to a module. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/parse/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/parse/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/parse/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/parse/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -65,24 +65,33 @@ let tts: &[TokenTree] = &tts[..]; match tts { - [TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), TokenTree::Token(Token { kind: token::Not, .. }), TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), TokenTree::Delimited(_, macro_delim, macro_tts)] - if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => - { + [ + TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), + TokenTree::Token(Token { kind: token::Not, .. }), + TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), + TokenTree::Delimited(_, macro_delim, macro_tts), + ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => { let tts = ¯o_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Delimited(_, first_delim, first_tts), TokenTree::Token(Token { kind: token::FatArrow, .. }), TokenTree::Delimited(_, second_delim, second_tts)] - if macro_delim == &token::Paren => - { + [ + TokenTree::Delimited(_, first_delim, first_tts), + TokenTree::Token(Token { kind: token::FatArrow, .. }), + TokenTree::Delimited(_, second_delim, second_tts), + ] if macro_delim == &token::Paren => { let tts = &first_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })] - if first_delim == &token::Paren && name.as_str() == "a" => {} + [ + TokenTree::Token(Token { kind: token::Dollar, .. }), + TokenTree::Token(Token { kind: token::Ident(name, false), .. }), + ] if first_delim == &token::Paren && name.as_str() == "a" => {} _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } let tts = &second_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })] - if second_delim == &token::Paren && name.as_str() == "a" => {} + [ + TokenTree::Token(Token { kind: token::Dollar, .. }), + TokenTree::Token(Token { kind: token::Ident(name, false), .. }), + ] if second_delim == &token::Paren && name.as_str() == "a" => {} _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/placeholders.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/placeholders.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/placeholders.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/placeholders.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,6 +46,13 @@ || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None }); match kind { + AstFragmentKind::Crate => AstFragment::Crate(ast::Crate { + attrs: Default::default(), + items: Default::default(), + span, + id, + is_placeholder: true, + }), AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { @@ -354,4 +361,12 @@ _ => noop_visit_ty(ty, self), } } + + fn visit_crate(&mut self, krate: &mut ast::Crate) { + if krate.is_placeholder { + *krate = self.remove(krate.id).make_crate(); + } else { + noop_visit_crate(krate, self) + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/proc_macro_server.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/proc_macro_server.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/proc_macro_server.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_expand/src/proc_macro_server.rs 2022-02-23 04:07:21.000000000 +0000 @@ -331,9 +331,9 @@ impl Ident { fn new(sess: &ParseSess, sym: Symbol, is_raw: bool, span: Span) -> Ident { - let sym = nfc_normalize(&sym.as_str()); + let sym = nfc_normalize(sym.as_str()); let string = sym.as_str(); - if !rustc_lexer::is_ident(&string) { + if !rustc_lexer::is_ident(string) { panic!("`{:?}` is not a valid identifier", string) } if is_raw && !sym.can_be_raw() { @@ -466,13 +466,12 @@ ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { ast::ExprKind::Lit(l) => match l.token { token::Lit { kind: token::Integer | token::Float, .. } => { - Ok(std::array::IntoIter::new([ + Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. tokenstream::TokenTree::token(token::BinOp(token::Minus), e.span), tokenstream::TokenTree::token(token::Literal(l.token), l.span), - ]) - .collect()) + ])) } _ => Err(()), }, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/accepted.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/accepted.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/accepted.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/accepted.rs 2022-02-23 04:07:21.000000000 +0000 @@ -90,6 +90,8 @@ (accepted, const_fn_union, "1.56.0", Some(51909), None), /// Allows unsizing coercions in `const fn`. (accepted, const_fn_unsize, "1.54.0", Some(64992), None), + /// Allows const generics to have default values (e.g. `struct Foo(...);`). + (accepted, const_generics_defaults, "1.59.0", Some(44580), None), /// Allows the use of `if` and `match` in constants. (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows indexing into constant arrays. @@ -112,6 +114,8 @@ (accepted, default_type_params, "1.0.0", None, None), /// Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows the use of destructuring assignments. + (accepted, destructuring_assignment, "1.59.0", Some(71126), None), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146), None), /// Allows `..` in tuple (struct) patterns. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/active.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/active.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/active.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/active.rs 2022-02-23 04:07:21.000000000 +0000 @@ -69,10 +69,6 @@ } } - pub fn unordered_const_ty_params(&self) -> bool { - self.const_generics_defaults || self.generic_const_exprs || self.adt_const_params - } - /// Some features are known to be incomplete and using them is likely to have /// unanticipated results, such as compiler crashes. We warn the user about these /// to alert them. @@ -290,6 +286,8 @@ (active, asm_experimental_arch, "1.58.0", Some(72016), None), /// Allows using `sym` operands in inline assembly. (active, asm_sym, "1.58.0", Some(72016), None), + /// Allows the `may_unwind` option in inline assembly. + (active, asm_unwind, "1.58.0", Some(72016), None), /// Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. @@ -332,8 +330,6 @@ (active, const_fn_trait_bound, "1.53.0", Some(57563), None), /// Allows `for _ in _` loops in const contexts. (active, const_for, "1.56.0", Some(87575), None), - /// Allows const generics to have default values (e.g. `struct Foo(...);`). - (active, const_generics_defaults, "1.51.0", Some(44580), None), /// Allows argument and return position `impl Trait` in a `const fn`. (active, const_impl_trait, "1.48.0", Some(77463), None), /// Allows using `&mut` in constant functions. @@ -360,8 +356,6 @@ (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), /// Allows `#[derive(Default)]` and `#[default]` on enums. (active, derive_default_enum, "1.56.0", Some(86985), None), - /// Allows the use of destructuring assignments. - (active, destructuring_assignment, "1.49.0", Some(71126), None), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/builtin_attrs.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/builtin_attrs.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/builtin_attrs.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_feature/src/builtin_attrs.rs 2022-02-23 04:07:21.000000000 +0000 @@ -339,7 +339,6 @@ ), // Entry point: - ungated!(main, Normal, template!(Word), WarnFollowing), ungated!(start, Normal, template!(Word), WarnFollowing), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_graphviz/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_graphviz/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_graphviz/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_graphviz/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -472,7 +472,7 @@ /// Escape tags in such a way that it is suitable for inclusion in a /// Graphviz HTML label. pub fn escape_html(s: &str) -> String { - s.replace("&", "&").replace("\"", """).replace("<", "<").replace(">", ">") + s.replace('&', "&").replace('\"', """).replace('<', "<").replace('>', ">") } impl<'a> LabelText<'a> { @@ -659,7 +659,7 @@ } writeln!(text, ";").unwrap(); - w.write_all(&text[..])?; + w.write_all(&text)?; text.clear(); } @@ -684,7 +684,7 @@ } writeln!(text, ";").unwrap(); - w.write_all(&text[..])?; + w.write_all(&text)?; text.clear(); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/arena.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/arena.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/arena.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/arena.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,6 +20,7 @@ [] generic_bound: rustc_hir::GenericBound<'tcx>, [] generic_param: rustc_hir::GenericParam<'tcx>, [] expr: rustc_hir::Expr<'tcx>, + [] let_expr: rustc_hir::Let<'tcx>, [] expr_field: rustc_hir::ExprField<'tcx>, [] pat_field: rustc_hir::PatField<'tcx>, [] fn_decl: rustc_hir::FnDecl<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/definitions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/definitions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/definitions.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/definitions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -101,7 +101,11 @@ pub struct Definitions { table: DefPathTable, - // FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners. + /// Only [`LocalDefId`]s for items and item-like are HIR owners. + /// The associated `HirId` has a `local_id` of `0`. + /// Generic parameters and closures are also assigned a `LocalDefId` but are not HIR owners. + /// Their `HirId`s are defined by their position while lowering the enclosing owner. + // FIXME(cjgillot) Some `LocalDefId`s from `use` items are dropped during lowering and lack a `HirId`. pub(super) def_id_to_hir_id: IndexVec>, /// The reverse mapping of `def_id_to_hir_id`. pub(super) hir_id_to_def_id: FxHashMap, @@ -173,7 +177,7 @@ if verbose && self.disambiguator != 0 { write!(writer, "{}#{}", name, self.disambiguator) } else { - writer.write_str(&name.as_str()) + writer.write_str(name.as_str()) } } DefPathDataName::Anon { namespace } => { @@ -267,6 +271,8 @@ // Different kinds of items and item-like things: /// An impl. Impl, + /// An `extern` block. + ForeignMod, /// Something in the type namespace. TypeNs(Symbol), /// Something in the value namespace. @@ -469,7 +475,9 @@ match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, + Impl | ForeignMod | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => { + None + } } } @@ -482,6 +490,7 @@ // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, + ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Misc => DefPathDataName::Anon { namespace: sym::misc }, ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, @@ -494,7 +503,7 @@ impl fmt::Display for DefPathData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.name() { - DefPathDataName::Named(name) => f.write_str(&name.as_str()), + DefPathDataName::Named(name) => f.write_str(name.as_str()), // FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace), } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/def.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/def.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/def.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/def.rs 2022-02-23 04:07:21.000000000 +0000 @@ -113,7 +113,7 @@ Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, - /// A use of [`global_asm!`]. + /// A use of `global_asm!`. GlobalAsm, Impl, Closure, @@ -443,11 +443,11 @@ } pub fn into_iter(self) -> IntoIter { - IntoIter::new([self.value_ns, self.type_ns, self.macro_ns]) + [self.value_ns, self.type_ns, self.macro_ns].into_iter() } pub fn iter(&self) -> IntoIter<&T, 3> { - IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns]) + [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } } @@ -481,7 +481,7 @@ /// Returns an iterator over the items which are `Some`. pub fn present_items(self) -> impl Iterator { - IntoIter::new([self.type_ns, self.value_ns, self.macro_ns]).flatten() + [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten() } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir_id.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir_id.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir_id.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir_id.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Encodable, Decodable)] pub struct HirId { pub owner: LocalDefId, @@ -32,6 +32,10 @@ pub fn make_owner(owner: LocalDefId) -> Self { Self { owner, local_id: ItemLocalId::from_u32(0) } } + + pub fn index(self) -> (usize, usize) { + (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id)) + } } impl fmt::Display for HirId { @@ -40,6 +44,18 @@ } } +impl Ord for HirId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + (self.index()).cmp(&(other.index())) + } +} + +impl PartialOrd for HirId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId); rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/hir.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,8 +17,7 @@ use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{def_id::LocalDefId, BytePos}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; @@ -92,7 +91,9 @@ Param(ParamName), /// User wrote nothing (e.g., the lifetime in `&u32`). - Implicit, + /// + /// The bool indicates whether the user should have written something. + Implicit(bool), /// Implicit lifetime in a context like `dyn Foo`. This is /// distinguished from implicit lifetimes elsewhere because the @@ -122,7 +123,7 @@ pub fn ident(&self) -> Ident { match *self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Error => Ident::empty(), LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), @@ -133,7 +134,7 @@ pub fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Underscore => true, // It might seem surprising that `Fresh(_)` counts as @@ -254,23 +255,9 @@ pub span: Span, } -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] -pub enum InferKind { - Const, - Type, -} - -impl InferKind { - #[inline] - pub fn is_type(self) -> bool { - matches!(self, InferKind::Type) - } -} - #[derive(Encodable, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, - pub kind: InferKind, pub span: Span, } @@ -324,13 +311,11 @@ } } - pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd { + pub fn to_ord(&self) -> ast::ParamKindOrd { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => { - ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } - } + GenericArg::Const(_) => ast::ParamKindOrd::Const, GenericArg::Infer(_) => ast::ParamKindOrd::Infer, } } @@ -523,13 +508,21 @@ pub kind: GenericParamKind<'hir>, } -impl GenericParam<'hir> { - pub fn bounds_span(&self) -> Option { - self.bounds.iter().fold(None, |span, bound| { - let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); - - Some(span) - }) +impl<'hir> GenericParam<'hir> { + pub fn bounds_span_for_suggestions(&self) -> Option { + self.bounds + .iter() + .fold(None, |span: Option, bound| { + // We include bounds that come from a `#[derive(_)]` but point at the user's code, + // as we use this method to get a span appropriate for suggestions. + if !bound.span().can_be_used_for_suggestions() { + None + } else { + let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); + Some(span) + } + }) + .map(|sp| sp.shrink_to_hi()) } } @@ -550,7 +543,7 @@ pub span: Span, } -impl Generics<'hir> { +impl<'hir> Generics<'hir> { pub const fn empty() -> Generics<'hir> { Generics { params: &[], @@ -615,7 +608,7 @@ EqPredicate(WhereEqPredicate<'hir>), } -impl WherePredicate<'_> { +impl<'hir> WherePredicate<'hir> { pub fn span(&self) -> Span { match self { WherePredicate::BoundPredicate(p) => p.span, @@ -637,7 +630,7 @@ pub bounds: GenericBounds<'hir>, } -impl WhereBoundPredicate<'hir> { +impl<'hir> WhereBoundPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. pub fn is_param_bound(&self, param_def_id: DefId) -> bool { let path = match self.bounded_ty.kind { @@ -1167,10 +1160,24 @@ pub body: &'hir Expr<'hir>, } +/// Represents a `let [: ] = ` expression (not a Local), occurring in an `if-let` or +/// `let-else`, evaluating to a boolean. Typically the pattern is refutable. +/// +/// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the +/// desugaring to if-let. Only let-else supports the type annotation at present. +#[derive(Debug, HashStable_Generic)] +pub struct Let<'hir> { + pub hir_id: HirId, + pub span: Span, + pub pat: &'hir Pat<'hir>, + pub ty: Option<&'hir Ty<'hir>>, + pub init: &'hir Expr<'hir>, +} + #[derive(Debug, HashStable_Generic)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), - // FIXME use ExprKind::Let for this. + // FIXME use hir::Let for this. IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>), } @@ -1196,7 +1203,7 @@ UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] pub struct BodyId { pub hir_id: HirId, } @@ -1229,7 +1236,7 @@ pub generator_kind: Option, } -impl Body<'hir> { +impl<'hir> Body<'hir> { pub fn id(&self) -> BodyId { BodyId { hir_id: self.value.hir_id } } @@ -1400,6 +1407,20 @@ /// A literal. pub type Lit = Spanned; +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +pub enum ArrayLen { + Infer(HirId, Span), + Body(AnonConst), +} + +impl ArrayLen { + pub fn hir_id(&self) -> HirId { + match self { + &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id, + } + } +} + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1620,13 +1641,13 @@ | LangItem::RangeFrom | LangItem::RangeFull | LangItem::RangeToInclusive, - _, + .. ) ), // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _))) + matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) } _ => false, @@ -1687,7 +1708,7 @@ /// /// These are not `Local` and only occur as expressions. /// The `let Some(x) = foo()` in `if let Some(x) = foo()` is an example of `Let(..)`. - Let(&'hir Pat<'hir>, &'hir Expr<'hir>, Span), + Let(&'hir Let<'hir>), /// An `if` block, with an optional else block. /// /// I.e., `if { } else { }`. @@ -1749,7 +1770,7 @@ /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, AnonConst), + Repeat(&'hir Expr<'hir>, ArrayLen), /// A suspension point for generators (i.e., `yield `). Yield(&'hir Expr<'hir>, YieldSource), @@ -1781,8 +1802,8 @@ /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - /// Reference to a `#[lang = "foo"]` item. - LangItem(LangItem, Span), + /// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr. + LangItem(LangItem, Span, Option), } impl<'hir> QPath<'hir> { @@ -1791,7 +1812,7 @@ match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1801,7 +1822,7 @@ match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1811,7 +1832,7 @@ match *self { QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span, QPath::TypeRelative(_, segment) => segment.ident.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } } @@ -1973,7 +1994,7 @@ // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct TraitItemId { pub def_id: LocalDefId, } @@ -2036,7 +2057,7 @@ // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ImplItemId { pub def_id: LocalDefId, } @@ -2239,7 +2260,6 @@ pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option, pub origin: OpaqueTyOrigin, } @@ -2247,9 +2267,9 @@ #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2260,7 +2280,7 @@ /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, AnonConst), + Array(&'hir Ty<'hir>, ArrayLen), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2478,7 +2498,7 @@ } } -#[derive(Encodable, Debug)] +#[derive(Encodable, Debug, HashStable_Generic)] pub struct Mod<'hir> { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -2617,7 +2637,7 @@ Unit(HirId), } -impl VariantData<'hir> { +impl<'hir> VariantData<'hir> { /// Return the fields of this variant. pub fn fields(&self) -> &'hir [FieldDef<'hir>] { match *self { @@ -2638,7 +2658,7 @@ // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, Hash)] pub struct ItemId { pub def_id: LocalDefId, } @@ -2800,7 +2820,9 @@ Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) @@ -2875,7 +2897,7 @@ // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ForeignItemId { pub def_id: LocalDefId, } @@ -3200,59 +3222,6 @@ } } - pub fn hir_id(&self) -> Option { - match self { - Node::Item(Item { def_id, .. }) - | Node::TraitItem(TraitItem { def_id, .. }) - | Node::ImplItem(ImplItem { def_id, .. }) - | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)), - Node::Field(FieldDef { hir_id, .. }) - | Node::AnonConst(AnonConst { hir_id, .. }) - | Node::Expr(Expr { hir_id, .. }) - | Node::Stmt(Stmt { hir_id, .. }) - | Node::Ty(Ty { hir_id, .. }) - | Node::Binding(Pat { hir_id, .. }) - | Node::Pat(Pat { hir_id, .. }) - | Node::Arm(Arm { hir_id, .. }) - | Node::Block(Block { hir_id, .. }) - | Node::Local(Local { hir_id, .. }) - | Node::Lifetime(Lifetime { hir_id, .. }) - | Node::Param(Param { hir_id, .. }) - | Node::Infer(InferArg { hir_id, .. }) - | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), - Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), - Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, - Node::Variant(Variant { id, .. }) => Some(*id), - Node::Ctor(variant) => variant.ctor_hir_id(), - Node::Crate(_) | Node::Visibility(_) => None, - } - } - - /// Returns `Constness::Const` when this node is a const fn/impl/item. - pub fn constness_for_typeck(&self) -> Constness { - match self { - Node::Item(Item { - kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::TraitItem(TraitItem { - kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::ImplItem(ImplItem { - kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, - - Node::Item(Item { kind: ItemKind::Const(..), .. }) - | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, - - _ => Constness::NotConst, - } - } - pub fn as_owner(self) -> Option> { match self { Node::Item(i) => Some(OwnerNode::Item(i)), @@ -3298,7 +3267,7 @@ rustc_data_structures::static_assert_size!(super::Expr<'static>, 64); rustc_data_structures::static_assert_size!(super::Pat<'static>, 88); rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); - rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); + rustc_data_structures::static_assert_size!(super::Ty<'static>, 80); rustc_data_structures::static_assert_size!(super::Item<'static>, 184); rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/intravisit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/intravisit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/intravisit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/intravisit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -139,7 +139,7 @@ } // Used when no map is actually available, forcing manual implementation of nested visitors. -impl Map<'hir> for ! { +impl<'hir> Map<'hir> for ! { fn find(&self, _: HirId) -> Option> { unreachable!() } @@ -383,12 +383,18 @@ fn visit_pat(&mut self, p: &'v Pat<'v>) { walk_pat(self, p) } + fn visit_array_length(&mut self, len: &'v ArrayLen) { + walk_array_len(self, len) + } fn visit_anon_const(&mut self, c: &'v AnonConst) { walk_anon_const(self, c) } fn visit_expr(&mut self, ex: &'v Expr<'v>) { walk_expr(self, ex) } + fn visit_let_expr(&mut self, lex: &'v Let<'v>) { + walk_let_expr(self, lex) + } fn visit_ty(&mut self, t: &'v Ty<'v>) { walk_ty(self, t) } @@ -545,7 +551,7 @@ | LifetimeName::Param(ParamName::Error) | LifetimeName::Static | LifetimeName::Error - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => {} } @@ -750,7 +756,7 @@ } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); - visitor.visit_anon_const(length) + visitor.visit_array_length(length) } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { for bound in bounds { @@ -1121,11 +1127,26 @@ } } +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { + match len { + &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id), + ArrayLen::Body(c) => visitor.visit_anon_const(c), + } +} + pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { visitor.visit_id(constant.hir_id); visitor.visit_nested_body(constant.body); } +pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) { + // match the visit order in walk_local + visitor.visit_expr(let_expr.init); + visitor.visit_id(let_expr.hir_id); + visitor.visit_pat(let_expr.pat); + walk_list!(visitor, visit_ty, let_expr.ty); +} + pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { visitor.visit_id(expression.hir_id); match expression.kind { @@ -1136,7 +1157,7 @@ ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), ExprKind::Repeat(ref element, ref count) => { visitor.visit_expr(element); - visitor.visit_anon_const(count) + visitor.visit_array_length(count) } ExprKind::Struct(ref qpath, fields, ref optional_base) => { visitor.visit_qpath(qpath, expression.hir_id, expression.span); @@ -1172,10 +1193,7 @@ ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } - ExprKind::Let(ref pat, ref expr, _) => { - visitor.visit_expr(expr); - visitor.visit_pat(pat); - } + ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr), ExprKind::If(ref cond, ref then, ref else_opt) => { visitor.visit_expr(cond); visitor.visit_expr(then); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lang_items.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lang_items.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lang_items.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lang_items.rs 2022-02-23 04:07:21.000000000 +0000 @@ -285,7 +285,6 @@ Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0); PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; - PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0); PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; @@ -348,6 +347,7 @@ ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None; ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None; + IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,6 @@ #![feature(const_btree_new)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] #![feature(never_type)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/stable_hash_impls.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/stable_hash_impls.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/stable_hash_impls.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir/src/stable_hash_impls.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ use crate::hir::{ AttributeMap, BodyId, Crate, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, - ItemId, Mod, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, + ItemId, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -16,7 +16,6 @@ fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher); fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher); fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher); - fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher); fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); @@ -132,12 +131,6 @@ } } -impl HashStable for Mod<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_hir_mod(self, hasher) - } -} - impl HashStable for Expr<'_> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { hcx.hash_hir_expr(self, hasher) @@ -211,7 +204,7 @@ } } -impl HashStable for OwnerNodes<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `nodes` and `bodies` fields since these refer to information included in // `hash` which is hashed in the collector and used for the crate hash. @@ -221,7 +214,7 @@ } } -impl HashStable for AttributeMap<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `hash` which is hashed in // the collector and used for the crate hash. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir_pretty/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir_pretty/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_hir_pretty/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_hir_pretty/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; -use rustc_span::{self, BytePos, FileName}; +use rustc_span::{self, FileName}; use rustc_target::spec::abi::Abi; use std::borrow::Cow; @@ -89,7 +89,7 @@ Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), Node::Arm(a) => self.print_arm(&a), - Node::Infer(_) => self.s.word("_"), + Node::Infer(_) => self.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); @@ -130,7 +130,7 @@ } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Name(&ident.name)) } @@ -194,7 +194,7 @@ pub fn visibility_qualified>>(vis: &hir::Visibility<'_>, w: S) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis); - s.s.word(w) + s.word(w) }) } @@ -241,40 +241,10 @@ } impl<'a> State<'a> { - pub fn cbox(&mut self, u: usize) { - self.s.cbox(u); - } - - pub fn nbsp(&mut self) { - self.s.word(" ") - } - - pub fn word_nbsp>>(&mut self, w: S) { - self.s.word(w); - self.nbsp() - } - - pub fn head>>(&mut self, w: S) { - let w = w.into(); - // outer-box is consistent - self.cbox(INDENT_UNIT); - // head-box is inconsistent - self.ibox(w.len() + 1); - // keyword that starts the head - if !w.is_empty() { - self.word_nbsp(w); - } - } - - pub fn bopen(&mut self) { - self.s.word("{"); - self.end(); // close the head-box - } - pub fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { self.maybe_print_comment(span.hi()); self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); - self.s.word("}"); + self.word("}"); if close_box { self.end(); // close the outer-box } @@ -284,33 +254,6 @@ self.bclose_maybe_open(span, true) } - pub fn space_if_not_bol(&mut self) { - if !self.s.is_beginning_of_line() { - self.s.space(); - } - } - - pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { - if !self.s.is_beginning_of_line() { - self.s.break_offset(n, off) - } else if off != 0 && self.s.last_token().is_hardbreak_tok() { - // We do something pretty sketchy here: tuck the nonzero - // offset-adjustment we were going to deposit along with the - // break into the previous hardbreak. - self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); - } - } - - // Synthesizes a comment that was not textually present in the original source - // file. - pub fn synth_comment(&mut self, text: String) { - self.s.word("/*"); - self.s.space(); - self.s.word(text); - self.s.space(); - self.s.word("*/") - } - pub fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) where F: FnMut(&mut State<'_>, &T), @@ -324,7 +267,7 @@ op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -355,27 +298,27 @@ self.ibox(0); match ty.kind { hir::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("]"); + self.word("]"); } hir::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } hir::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } hir::TyKind::Never => { - self.s.word("!"); + self.word("!"); } hir::TyKind::Tup(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, &elts, |s, ty| s.print_type(&ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -389,7 +332,7 @@ f.param_names, ); } - hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"), + hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -412,24 +355,24 @@ } } hir::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("; "); - self.print_anon_const(length); - self.s.word("]"); + self.word("; "); + self.print_array_length(length); + self.word("]"); } hir::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_anon_const(e); - self.s.word(")"); + self.word(")"); } hir::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } hir::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } } self.end() @@ -457,7 +400,7 @@ None, ); self.end(); // end head-ibox - self.s.word(";"); + self.word(";"); self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { @@ -468,14 +411,14 @@ self.print_ident(item.ident); self.word_space(":"); self.print_type(&t); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } hir::ForeignItemKind::Type => { self.head(visibility_qualified(&item.vis, "type")); self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } @@ -489,17 +432,17 @@ default: Option, vis: &hir::Visibility<'_>, ) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); self.word_space("const"); self.print_ident(ident); self.word_space(":"); self.print_type(ty); if let Some(expr) = default { - self.s.space(); + self.space(); self.word_space("="); self.ann.nested(self, Nested::Body(expr)); } - self.s.word(";") + self.word(";") } fn print_associated_type( @@ -517,11 +460,11 @@ } self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";") + self.word(";") } fn print_item_type( @@ -536,9 +479,9 @@ self.end(); // end the inner ibox self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); inner(self); - self.s.word(";"); + self.word(";"); self.end(); // end the outer ibox } @@ -554,12 +497,12 @@ self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -570,14 +513,14 @@ match kind { hir::UseKind::Single => { if path.segments.last().unwrap().ident != item.ident { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(item.ident); } - self.s.word(";"); + self.word(";"); } - hir::UseKind::Glob => self.s.word("::*;"), - hir::UseKind::ListStem => self.s.word("::{};"), + hir::UseKind::Glob => self.word("::*;"), + hir::UseKind::ListStem => self.word("::{};"), } self.end(); // end inner head-block self.end(); // end outer head-block @@ -590,12 +533,12 @@ self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { @@ -603,12 +546,12 @@ self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Fn(ref sig, ref param_names, body) => { @@ -622,7 +565,7 @@ &[], Some(body), ); - self.s.word(" "); + self.word(" "); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); @@ -666,7 +609,7 @@ let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); for b in opaque_ty.bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - state.s.space(); + state.space(); state.word_space("for ?"); state.print_trait_ref(&ptr.trait_ref); } else { @@ -706,7 +649,7 @@ if !generics.params.is_empty() { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } if constness == hir::Constness::Const { @@ -714,19 +657,19 @@ } if let hir::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(&self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(attrs); for impl_item in items { @@ -745,7 +688,7 @@ let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -754,7 +697,7 @@ } self.print_bounds(":", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); for trait_item in trait_items { self.ann.nested(self, Nested::TraitItem(trait_item.id)); @@ -771,7 +714,7 @@ // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -781,7 +724,7 @@ self.nbsp(); self.print_bounds("=", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } } self.ann.post(self, AnnNode::Item(item)) @@ -793,7 +736,7 @@ fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -816,7 +759,7 @@ self.print_name(name); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -828,7 +771,7 @@ self.print_outer_attributes(self.attrs(v.id)); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } @@ -841,10 +784,10 @@ hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"), hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"), hir::VisibilityKind::Restricted { ref path, .. } => { - self.s.word("pub("); + self.word("pub("); if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super { // Special case: `super` can print like `pub(super)`. - self.s.word("super"); + self.word("super"); } else { // Everything else requires `in` at present. self.word_nbsp("in"); @@ -887,7 +830,7 @@ } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end() // close the outer-box @@ -906,7 +849,7 @@ self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(&field.ty); - self.s.word(","); + self.word(","); } self.bclose(span) @@ -919,7 +862,7 @@ let generics = hir::Generics::empty(); self.print_struct(&v.data, &generics, v.ident.name, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(d); } @@ -951,7 +894,7 @@ let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); - self.s.word(";"); + self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let vis = @@ -1032,11 +975,11 @@ hir::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr(&expr); - self.s.word(";"); + self.word(";"); } } if stmt_ends_with_semi(&st.kind) { - self.s.word(";"); + self.word(";"); } self.maybe_print_trailing_comment(st.span, None) } @@ -1088,9 +1031,9 @@ hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(&i); - self.s.space(); + self.space(); self.print_expr(&then); self.print_else(e.as_ref().map(|e| &**e)) } @@ -1098,7 +1041,7 @@ hir::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(&b) } // Constraints would be great here! @@ -1117,11 +1060,18 @@ ) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_expr(blk); self.print_else(elseopt) } + pub fn print_array_length(&mut self, len: &hir::ArrayLen) { + match len { + hir::ArrayLen::Infer(_, _) => self.word("_"), + hir::ArrayLen::Body(ct) => self.print_anon_const(ct), + } + } + pub fn print_anon_const(&mut self, constant: &hir::AnonConst) { self.ann.nested(self, Nested::Body(constant.body)) } @@ -1158,13 +1108,17 @@ } /// Print a `let pat = expr` expression. - fn print_let(&mut self, pat: &hir::Pat<'_>, expr: &hir::Expr<'_>) { - self.s.word("let "); + fn print_let(&mut self, pat: &hir::Pat<'_>, ty: Option<&hir::Ty<'_>>, init: &hir::Expr<'_>) { + self.word_space("let"); self.print_pat(pat); - self.s.space(); + if let Some(ty) = ty { + self.word_space(":"); + self.print_type(ty); + } + self.space(); self.word_space("="); - let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); - self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) + let npals = || parser::needs_par_as_let_scrutinee(init.precedence().order()); + self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals()) } // Does `expr` need parentheses when printed in a condition position? @@ -1180,26 +1134,26 @@ fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end() } fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word_space("const"); + self.word_space("const"); self.print_anon_const(anon_const); self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); - self.print_anon_const(count); - self.s.word("]"); + self.print_array_length(count); + self.word("]"); self.end() } @@ -1210,7 +1164,7 @@ wth: &Option<&hir::Expr<'_>>, ) { self.print_qpath(qpath, true); - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1229,27 +1183,27 @@ Some(ref expr) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); self.print_expr(&expr); self.end(); } _ => { if !fields.is_empty() { - self.s.word(",") + self.word(",") } } } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1267,7 +1221,7 @@ fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); let generic_args = segment.args(); @@ -1303,13 +1257,13 @@ }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.as_str()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { - self.s.word(op.as_str()); + self.word(op.as_str()); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1319,7 +1273,7 @@ mutability: hir::Mutability, expr: &hir::Expr<'_>, ) { - self.s.word("&"); + self.word("&"); match kind { hir::BorrowKind::Ref => self.print_mutability(mutability, false), hir::BorrowKind::Raw => { @@ -1433,6 +1387,9 @@ if opts.contains(ast::InlineAsmOptions::RAW) { options.push("raw"); } + if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); @@ -1488,7 +1445,7 @@ hir::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(&expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(&ty); } @@ -1507,7 +1464,7 @@ // Print `let _t = $init;`: let temp = Ident::from_str("_t"); self.print_local(Some(init), |this| this.print_ident(temp)); - self.s.word(";"); + self.word(";"); // Print `_t`: self.space_if_not_bol(); @@ -1516,8 +1473,8 @@ // Print `}`: self.bclose_maybe_open(expr.span, true); } - hir::ExprKind::Let(ref pat, ref scrutinee, _) => { - self.print_let(pat, scrutinee); + hir::ExprKind::Let(hir::Let { pat, ty, init, .. }) => { + self.print_let(pat, *ty, init); } hir::ExprKind::If(ref test, ref blk, ref elseopt) => { self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)); @@ -1535,7 +1492,7 @@ self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(&expr); - self.s.space(); + self.space(); self.bopen(); for arm in arms { self.print_arm(arm); @@ -1546,7 +1503,7 @@ self.print_capture_clause(capture_clause); self.print_closure_params(&decl, body); - self.s.space(); + self.space(); // This is a bare expression. self.ann.nested(self, Nested::Body(body)); @@ -1571,54 +1528,52 @@ hir::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); - self.s.word(op.node.as_str()); + self.space(); + self.word(op.node.as_str()); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } hir::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(&index); - self.s.word("]"); + self.word("]"); } hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true), hir::ExprKind::Break(destination, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); if let Some(label) = destination.label { + self.space(); self.print_ident(label.ident); - self.s.space(); } if let Some(ref expr) = *opt_expr { + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); } } hir::ExprKind::Continue(destination) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); if let Some(label) = destination.label { + self.space(); self.print_ident(label.ident); - self.s.space() } } hir::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); } } @@ -1628,7 +1583,7 @@ } hir::ExprKind::LlvmInlineAsm(ref a) => { let i = &a.inner; - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(i.asm, i.asm_str_style); self.word_space(":"); @@ -1648,7 +1603,7 @@ s.pclose(); out_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); let mut in_idx = 0; @@ -1659,7 +1614,7 @@ s.pclose(); in_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &i.clobbers, |s, &co| { @@ -1678,7 +1633,7 @@ } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -1693,7 +1648,7 @@ } hir::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } } @@ -1718,7 +1673,7 @@ for (i, segment) in path.segments.iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1738,14 +1693,14 @@ match *qpath { hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params), hir::QPath::Resolved(Some(ref qself), ref path) => { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.space(); + self.space(); self.word_space("as"); for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1757,8 +1712,8 @@ } } - self.s.word(">"); - self.s.word("::"); + self.word(">"); + self.word("::"); let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident); self.print_generic_args( @@ -1774,12 +1729,12 @@ if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind { self.print_type(qself); } else { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.word(">"); + self.word(">"); } - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); self.print_generic_args( item_segment.args(), @@ -1787,10 +1742,10 @@ colons_before_params, ) } - hir::QPath::LangItem(lang_item, span) => { - self.s.word("#[lang = \""); + hir::QPath::LangItem(lang_item, span, _) => { + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), span)); - self.s.word("\"]"); + self.word("\"]"); } } } @@ -1802,9 +1757,9 @@ colons_before_params: bool, ) { if generic_args.parenthesized { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty)); - self.s.word(")"); + self.word(")"); self.space_if_not_bol(); self.word_space("->"); @@ -1815,7 +1770,7 @@ let start_or_comma = |this: &mut Self| { if empty.get() { empty.set(false); - this.s.word(start) + this.word(start) } else { this.word_space(",") } @@ -1849,14 +1804,14 @@ // "non-exhaustive patterns: `Some::<..>(_)` not covered"). if infer_args && false { start_or_comma(self); - self.s.word(".."); + self.word(".."); } for binding in generic_args.bindings.iter() { start_or_comma(self); self.print_ident(binding.ident); self.print_generic_args(binding.gen_args, false, false); - self.s.space(); + self.space(); match generic_args.bindings[0].kind { hir::TypeBindingKind::Equality { ref ty } => { self.word_space("="); @@ -1869,7 +1824,7 @@ } if !empty.get() { - self.s.word(">") + self.word(">") } } } @@ -1880,7 +1835,7 @@ // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Binding(binding_mode, _, ident, ref sub) => { match binding_mode { hir::BindingAnnotation::Ref => { @@ -1898,7 +1853,7 @@ } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.word("@"); + self.word("@"); self.print_pat(&p); } } @@ -1910,13 +1865,13 @@ if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(&p)); } self.pclose(); } @@ -1926,10 +1881,14 @@ PatKind::Struct(ref qpath, ref fields, etc) => { self.print_qpath(qpath, true); self.nbsp(); - self.word_space("{"); + self.word("{"); + let empty = fields.is_empty() && !etc; + if !empty { + self.space(); + } self.commasep_cmnt( Consistent, - &fields[..], + &fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { @@ -1945,13 +1904,15 @@ if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); + } + if !empty { + self.space(); } - self.s.space(); - self.s.word("}"); + self.word("}"); } PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p)); + self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(&p)); } PatKind::Tuple(ref elts, ddpos) => { self.popen(); @@ -1960,22 +1921,22 @@ if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } } self.pclose(); } PatKind::Box(ref inner) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("box "); + self.word("box "); if is_range_inner { self.popen(); } @@ -1986,8 +1947,8 @@ } PatKind::Ref(ref inner, mutbl) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("&"); - self.s.word(mutbl.prefix_str()); + self.word("&"); + self.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } @@ -2000,19 +1961,18 @@ PatKind::Range(ref begin, ref end, ref end_kind) => { if let Some(expr) = begin { self.print_expr(expr); - self.s.space(); } match *end_kind { - RangeEnd::Included => self.s.word("..."), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included => self.word("..."), + RangeEnd::Excluded => self.word(".."), } if let Some(expr) = end { self.print_expr(expr); } } PatKind::Slice(ref before, ref slice, ref after) => { - self.s.word("["); - self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p)); + self.word("["); + self.commasep(Inconsistent, &before, |s, p| s.print_pat(&p)); if let Some(ref p) = *slice { if !before.is_empty() { self.word_space(","); @@ -2022,13 +1982,13 @@ } else { self.print_pat(&p); } - self.s.word(".."); + self.word(".."); if !after.is_empty() { self.word_space(","); } } - self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p)); - self.s.word("]"); + self.commasep(Inconsistent, &after, |s, p| s.print_pat(&p)); + self.word("]"); } } self.ann.post(self, AnnNode::Pat(pat)) @@ -2043,29 +2003,29 @@ // I have no idea why this check is necessary, but here it // is :( if self.attrs(arm.hir_id).is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); self.print_outer_attributes(&self.attrs(arm.hir_id)); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref g) = arm.guard { match g { hir::Guard::If(e) => { self.word_space("if"); self.print_expr(&e); - self.s.space(); + self.space(); } hir::Guard::IfLet(pat, e) => { self.word_nbsp("if"); self.word_nbsp("let"); self.print_pat(&pat); - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&e); - self.s.space(); + self.space(); } } } @@ -2083,13 +2043,13 @@ // If it is a user-provided unsafe block, print a comma after it if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // close the ibox for the pattern self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.ann.post(self, AnnNode::Arm(arm)); @@ -2121,20 +2081,20 @@ self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); if let Some(arg_name) = arg_names.get(i) { - s.s.word(arg_name.to_string()); - s.s.word(":"); - s.s.space(); + s.word(arg_name.to_string()); + s.word(":"); + s.space(); } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); } i += 1; s.print_type(ty); s.end() }); if decl.c_variadic { - self.s.word(", ..."); + self.word(", ..."); } self.pclose(); @@ -2143,7 +2103,7 @@ } fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { - self.s.word("|"); + self.word("|"); let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); @@ -2154,13 +2114,13 @@ if let hir::TyKind::Infer = ty.kind { // Print nothing. } else { - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); s.print_type(ty); } s.end(); }); - self.s.word("|"); + self.word("|"); if let hir::FnRetTy::DefaultReturn(..) = decl.output { return; @@ -2171,7 +2131,7 @@ match decl.output { hir::FnRetTy::Return(ref ty) => { self.print_type(&ty); - self.maybe_print_comment(ty.span.lo()) + self.maybe_print_comment(ty.span.lo()); } hir::FnRetTy::DefaultReturn(..) => unreachable!(), } @@ -2192,7 +2152,7 @@ let mut first = true; for bound in bounds { if first { - self.s.word(prefix); + self.word(prefix); } if !(first && prefix.is_empty()) { self.nbsp(); @@ -2206,14 +2166,14 @@ match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } GenericBound::LangItemTrait(lang_item, span, ..) => { - self.s.word("#[lang = \""); + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), *span)); - self.s.word("\"]"); + self.word("\"]"); } GenericBound::Outlives(lt) => { self.print_lifetime(lt); @@ -2224,11 +2184,11 @@ pub fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param)); - self.s.word(">"); + self.word(">"); } } @@ -2245,7 +2205,7 @@ for bound in param.bounds { match bound { GenericBound::Outlives(ref lt) => { - self.s.word(sep); + self.word(sep); self.print_lifetime(lt); sep = "+"; } @@ -2256,7 +2216,7 @@ GenericParamKind::Type { ref default, .. } => { self.print_bounds(":", param.bounds); if let Some(default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_type(&default) } @@ -2265,7 +2225,7 @@ self.word_space(":"); self.print_type(ty); if let Some(ref default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(&default) } @@ -2282,7 +2242,7 @@ return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2307,7 +2267,7 @@ .. }) => { self.print_lifetime(lifetime); - self.s.word(":"); + self.word(":"); for (i, bound) in bounds.iter().enumerate() { match bound { @@ -2318,7 +2278,7 @@ } if i != 0 { - self.s.word(":"); + self.word(":"); } } } @@ -2326,7 +2286,7 @@ lhs_ty, rhs_ty, .. }) => { self.print_type(lhs_ty); - self.s.space(); + self.space(); self.word_space("="); self.print_type(rhs_ty); } @@ -2365,7 +2325,7 @@ self.end(); if let hir::FnRetTy::Return(ref output) = decl.output { - self.maybe_print_comment(output.span.lo()) + self.maybe_print_comment(output.span.lo()); } } @@ -2379,10 +2339,7 @@ arg_names: &[Ident], ) { self.ibox(INDENT_UNIT); - if !generic_params.is_empty() { - self.s.word("for"); - self.print_generic_params(generic_params); - } + self.print_formal_generic_params(generic_params); let generics = hir::Generics { params: &[], where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP }, @@ -2405,31 +2362,8 @@ self.end(); } - pub fn maybe_print_trailing_comment( - &mut self, - span: rustc_span::Span, - next_pos: Option, - ) { - if let Some(cmnts) = self.comments() { - if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { - self.print_comment(&cmnt); - } - } - } - - pub fn print_remaining_comments(&mut self) { - // If there aren't any remaining comments, then we need to manually - // make sure there is a line break at the end. - if self.next_comment().is_none() { - self.s.hardbreak(); - } - while let Some(ref cmnt) = self.next_comment() { - self.print_comment(cmnt) - } - } - pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); match header.constness { hir::Constness::NotConst => {} @@ -2448,7 +2382,7 @@ self.word_nbsp(header.abi.to_string()); } - self.s.word("fn") + self.word("fn") } pub fn print_unsafety(&mut self, s: hir::Unsafety) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_dep_graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_dep_graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_dep_graph.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_dep_graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -52,6 +52,7 @@ use std::fs::{self, File}; use std::io::{BufWriter, Write}; +#[allow(missing_docs)] pub fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.debugging_opts.dump_dep_graph { @@ -102,7 +103,7 @@ then_this_would_need: Targets, } -impl IfThisChanged<'tcx> { +impl<'tcx> IfThisChanged<'tcx> { fn argument(&self, attr: &ast::Attribute) -> Option { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { @@ -130,7 +131,7 @@ DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) } Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -146,7 +147,7 @@ let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -171,7 +172,7 @@ } } -impl Visitor<'tcx> for IfThisChanged<'tcx> { +impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -262,6 +263,7 @@ } } +#[allow(missing_docs)] pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>); impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_module_sources.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_module_sources.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_module_sources.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/assert_module_sources.rs 2022-02-23 04:07:21.000000000 +0000 @@ -29,6 +29,7 @@ use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeSet; +#[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.incremental.is_none() { @@ -55,7 +56,7 @@ available_cgus: BTreeSet, } -impl AssertModuleSource<'tcx> { +impl<'tcx> AssertModuleSource<'tcx> { fn check_attr(&self, attr: &ast::Attribute) { let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { (CguReuse::PreLto, ComparisonKind::AtLeast) @@ -123,7 +124,7 @@ debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); - if !self.available_cgus.contains(&*cgu_name.as_str()) { + if !self.available_cgus.contains(cgu_name.as_str()) { self.tcx.sess.span_err( attr.span, &format!( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ //! Support for serializing the dep-graph and reloading it. +#![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,6 +9,13 @@ //! - `#[rustc_clean(cfg="rev2")]` same as above, except that the //! fingerprints must be the SAME (along with all other fingerprints). //! +//! - `#[rustc_clean(cfg="rev2", loaded_from_disk='typeck")]` asserts that +//! the query result for `DepNode::typeck(X)` was actually +//! loaded from disk (not just marked green). This can be useful +//! to ensure that a test is actually exercising the deserialization +//! logic for a particular query result. This can be combined with +//! `except` +//! //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. @@ -28,6 +35,7 @@ use std::iter::FromIterator; use std::vec::Vec; +const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; const EXCEPT: Symbol = sym::except; const CFG: Symbol = sym::cfg; @@ -124,6 +132,7 @@ struct Assertion { clean: Labels, dirty: Labels, + loaded_from_disk: Labels, } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { @@ -155,7 +164,7 @@ checked_attrs: FxHashSet, } -impl DirtyCleanVisitor<'tcx> { +impl<'tcx> DirtyCleanVisitor<'tcx> { /// Possibly "deserialize" the attribute into a clean/dirty assertion fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { if !attr.has_name(sym::rustc_clean) { @@ -174,6 +183,7 @@ fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion { let (name, mut auto) = self.auto_labels(item_id, attr); let except = self.except(attr); + let loaded_from_disk = self.loaded_from_disk(attr); for e in except.iter() { if !auto.remove(e) { let msg = format!( @@ -183,7 +193,19 @@ self.tcx.sess.span_fatal(attr.span, &msg); } } - Assertion { clean: auto, dirty: except } + Assertion { clean: auto, dirty: except, loaded_from_disk } + } + + /// `loaded_from_disk=` attribute value + fn loaded_from_disk(&self, attr: &Attribute) -> Labels { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.has_name(LOADED_FROM_DISK) { + let value = expect_associated_value(self.tcx, &item); + return self.resolve_labels(&item, value); + } + } + // If `loaded_from_disk=` is not specified, don't assert anything + Labels::default() } /// `except=` attribute value @@ -332,6 +354,18 @@ } } + fn assert_loaded_from_disk(&self, item_span: Span, dep_node: DepNode) { + debug!("assert_loaded_from_disk({:?})", dep_node); + + if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) { + let dep_node_str = self.dep_node_str(&dep_node); + self.tcx.sess.span_err( + item_span, + &format!("`{}` should have been loaded from disk but it was not", dep_node_str), + ); + } + } + fn check_item(&mut self, item_id: LocalDefId, item_span: Span) { let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { @@ -348,11 +382,15 @@ let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); self.assert_dirty(item_span, dep_node); } + for label in assertion.loaded_from_disk { + let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + self.assert_loaded_from_disk(item_span, dep_node); + } } } } -impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.check_item(item.def_id, item.span); } @@ -382,7 +420,7 @@ let value = expect_associated_value(tcx, &item); debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); - } else if !item.has_name(EXCEPT) { + } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty())); } } @@ -415,7 +453,7 @@ found_attrs: Vec<&'tcx Attribute>, } -impl FindAllAttrs<'tcx> { +impl<'tcx> FindAllAttrs<'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { return true; @@ -434,7 +472,7 @@ } } -impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { +impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/fs.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/fs.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/fs.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/fs.rs 2022-02-23 04:07:21.000000000 +0000 @@ -133,21 +133,26 @@ // case-sensitive (as opposed to base64, for example). const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; +/// Returns the path to a session's dependency graph. pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +/// Returns the path to a session's staging dependency graph. +/// +/// On the difference between dep-graph and staging dep-graph, +/// see `build_dep_graph`. pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) } - pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME) } - +/// Returns the path to a session's query cache. pub fn query_cache_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME) } +/// Locks a given session directory. pub fn lock_file_path(session_dir: &Path) -> PathBuf { let crate_dir = session_dir.parent().unwrap(); @@ -166,23 +171,35 @@ crate_dir.join(&directory_name[0..dash_indices[2]]).with_extension(&LOCK_FILE_EXT[1..]) } +/// Returns the path for a given filename within the incremental compilation directory +/// in the current session. pub fn in_incr_comp_dir_sess(sess: &Session, file_name: &str) -> PathBuf { in_incr_comp_dir(&sess.incr_comp_session_dir(), file_name) } +/// Returns the path for a given filename within the incremental compilation directory, +/// not necessarily from the current session. +/// +/// To ensure the file is part of the current session, use [`in_incr_comp_dir_sess`]. pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBuf { incr_comp_session_dir.join(file_name) } -/// Allocates the private session directory. The boolean in the Ok() result -/// indicates whether we should try loading a dep graph from the successfully -/// initialized directory, or not. -/// The post-condition of this fn is that we have a valid incremental -/// compilation session directory, if the result is `Ok`. A valid session +/// Allocates the private session directory. +/// +/// If the result of this function is `Ok`, we have a valid incremental +/// compilation session directory. A valid session /// directory is one that contains a locked lock file. It may or may not contain /// a dep-graph and work products from a previous session. -/// If the call fails, the fn may leave behind an invalid session directory. +/// +/// This always attempts to load a dep-graph from the directory. +/// If loading fails for some reason, we fallback to a disabled `DepGraph`. +/// See [`rustc_interface::queries::dep_graph`]. +/// +/// If this function returns an error, it may leave behind an invalid session directory. /// The garbage collection will take care of it. +/// +/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph pub fn prepare_session_directory( sess: &Session, crate_name: &str, @@ -661,6 +678,7 @@ timestamp < SystemTime::now() - Duration::from_secs(10) } +/// Runs garbage collection for the current session. pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/load.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/load.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/load.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/load.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,13 +18,24 @@ type WorkProductMap = FxHashMap; #[derive(Debug)] +/// Represents the result of an attempt to load incremental compilation data. pub enum LoadResult { - Ok { data: T }, + /// Loading was successful. + Ok { + #[allow(missing_docs)] + data: T, + }, + /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - Error { message: String }, + /// An error occured. + Error { + #[allow(missing_docs)] + message: String, + }, } impl LoadResult { + /// Accesses the data returned in [`LoadResult::Ok`]. pub fn open(self, sess: &Session) -> T { // Check for errors when using `-Zassert-incremental-state` match (sess.opts.assert_incr_state, &self) { @@ -99,6 +110,7 @@ } impl MaybeAsync> { + /// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible. pub fn open(self) -> LoadResult { match self { MaybeAsync::Sync(result) => result, @@ -109,6 +121,7 @@ } } +/// An asynchronous type for computing the dependency graph. pub type DepGraphFuture = MaybeAsync>; /// Launch a thread and load the dependency graph in the background. @@ -151,7 +164,7 @@ compilation session directory: {}", e ); - sess.fatal(&msg[..]) + sess.fatal(&msg) }); for swp in work_products { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/save.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/save.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/save.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/save.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,9 +13,13 @@ use super::fs::*; use super::work_product; -/// Save and dump the DepGraph. +/// Saves and writes the [`DepGraph`] to the file system. /// -/// No query must be invoked after this function. +/// This function saves both the dep-graph and the query result cache, +/// and drops the result cache. +/// +/// This function should only run after all queries have completed. +/// Trying to execute a query afterwards would attempt to read the result cache we just dropped. pub fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { @@ -75,6 +79,7 @@ }) } +/// Saves the work product index. pub fn save_work_product_index( sess: &Session, dep_graph: &DepGraph, @@ -139,6 +144,12 @@ tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) } +/// Builds the dependency graph. +/// +/// This function breates the *staging dep-graph*. When the dep-graph is modified by a query +/// execution, the new dependency information is not kept in memory but directly +/// output to this file. `save_dep_graph` then finalizes the staging dep-graph +/// and moves it to the permanent dep-graph path pub fn build_dep_graph( sess: &Session, prev_graph: SerializedDepGraph, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/work_product.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/work_product.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/work_product.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_incremental/src/persist/work_product.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,6 @@ -//! This module contains files for saving intermediate work-products. +//! Functions for saving and removing intermediate [work products]. +//! +//! [work products]: WorkProduct use crate::persist::fs::*; use rustc_fs_util::link_or_copy; @@ -7,6 +9,7 @@ use std::fs as std_fs; use std::path::PathBuf; +/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it. pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, @@ -40,6 +43,7 @@ Some((work_product_id, work_product)) } +/// Removes files for a given work product. pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { if let Some(ref file_name) = work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -10,3 +10,4 @@ arrayvec = { version = "0.7", default-features = false } rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } +smallvec = "1" diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/bit_set.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/bit_set.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/bit_set.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/bit_set.rs 2022-02-23 04:07:21.000000000 +0000 @@ -87,7 +87,7 @@ /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. /// -#[derive(Eq, PartialEq, Decodable, Encodable)] +#[derive(Eq, PartialEq, Hash, Decodable, Encodable)] pub struct BitSet { domain_size: usize, words: Vec, @@ -675,7 +675,7 @@ fn insert(&mut self, elem: T) -> bool { assert!(elem.index() < self.domain_size); - let changed = if let Some(i) = self.elems.iter().position(|&e| e >= elem) { + let changed = if let Some(i) = self.elems.iter().position(|&e| e.index() >= elem.index()) { if self.elems[i] == elem { // `elem` is already in the set. false @@ -715,6 +715,10 @@ self.elems.iter() } + bit_relations_inherent_impls! {} +} + +impl SparseBitSet { fn last_set_in(&self, range: impl RangeBounds) -> Option { let mut last_leq = None; for e in self.iter() { @@ -724,8 +728,6 @@ } last_leq } - - bit_relations_inherent_impls! {} } /// A fixed-size bitset type with a hybrid representation: sparse when there @@ -802,7 +804,10 @@ /// Returns the previous element present in the bitset from `elem`, /// inclusively of elem. That is, will return `Some(elem)` if elem is in the /// bitset. - pub fn last_set_in(&self, range: impl RangeBounds) -> Option { + pub fn last_set_in(&self, range: impl RangeBounds) -> Option + where + T: Ord, + { match self { HybridBitSet::Sparse(sparse) => sparse.last_set_in(range), HybridBitSet::Dense(dense) => dense.last_set_in(range), @@ -987,7 +992,7 @@ /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Eq, PartialEq, Decodable, Encodable)] +#[derive(Clone, Eq, PartialEq, Hash, Decodable, Encodable)] pub struct BitMatrix { num_rows: usize, num_columns: usize, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,199 @@ +use super::*; + +#[test] +fn insert_collapses() { + let mut set = IntervalSet::::new(3000); + set.insert_range(9831..=9837); + set.insert_range(43..=9830); + assert_eq!(set.iter_intervals().collect::>(), [43..9838]); +} + +#[test] +fn contains() { + let mut set = IntervalSet::new(300); + set.insert(0u32); + assert!(set.contains(0)); + set.insert_range(0..10); + assert!(set.contains(9)); + assert!(!set.contains(10)); + set.insert_range(10..11); + assert!(set.contains(10)); +} + +#[test] +fn insert() { + for i in 0..30usize { + let mut set = IntervalSet::new(300); + for j in i..30usize { + set.insert(j); + for k in i..j { + assert!(set.contains(k)); + } + } + } + + let mut set = IntervalSet::new(300); + set.insert_range(0..1u32); + assert!(set.contains(0), "{:?}", set.map); + assert!(!set.contains(1)); + set.insert_range(1..1); + assert!(set.contains(0)); + assert!(!set.contains(1)); + + let mut set = IntervalSet::new(300); + set.insert_range(4..5u32); + set.insert_range(5..10); + assert_eq!(set.iter().collect::>(), [4, 5, 6, 7, 8, 9]); + set.insert_range(3..7); + assert_eq!(set.iter().collect::>(), [3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(3..5); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(0..3); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(0..10); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(5..10); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(5..13); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); +} + +#[test] +fn insert_range() { + #[track_caller] + fn check(range: R) + where + R: RangeBounds + Clone + IntoIterator + std::fmt::Debug, + { + let mut set = IntervalSet::new(300); + set.insert_range(range.clone()); + for i in set.iter() { + assert!(range.contains(&i)); + } + for i in range.clone() { + assert!(set.contains(i), "A: {} in {:?}, inserted {:?}", i, set, range); + } + set.insert_range(range.clone()); + for i in set.iter() { + assert!(range.contains(&i), "{} in {:?}", i, set); + } + for i in range.clone() { + assert!(set.contains(i), "B: {} in {:?}, inserted {:?}", i, set, range); + } + } + check(10..10); + check(10..100); + check(10..30); + check(0..5); + check(0..250); + check(200..250); + + check(10..=10); + check(10..=100); + check(10..=30); + check(0..=5); + check(0..=250); + check(200..=250); + + for i in 0..30 { + for j in i..30 { + check(i..j); + check(i..=j); + } + } +} + +#[test] +fn insert_range_dual() { + let mut set = IntervalSet::::new(300); + set.insert_range(0..3); + assert_eq!(set.iter().collect::>(), [0, 1, 2]); + set.insert_range(5..7); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 5, 6]); + set.insert_range(3..4); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 5, 6]); + set.insert_range(3..5); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6]); +} + +#[test] +fn last_set_before_adjacent() { + let mut set = IntervalSet::::new(300); + set.insert_range(0..3); + set.insert_range(3..5); + assert_eq!(set.last_set_in(0..3), Some(2)); + assert_eq!(set.last_set_in(0..5), Some(4)); + assert_eq!(set.last_set_in(3..5), Some(4)); + set.insert_range(2..5); + assert_eq!(set.last_set_in(0..3), Some(2)); + assert_eq!(set.last_set_in(0..5), Some(4)); + assert_eq!(set.last_set_in(3..5), Some(4)); +} + +#[test] +fn last_set_in() { + fn easy(set: &IntervalSet, needle: impl RangeBounds) -> Option { + let mut last_leq = None; + for e in set.iter() { + if needle.contains(&e) { + last_leq = Some(e); + } + } + last_leq + } + + #[track_caller] + fn cmp(set: &IntervalSet, needle: impl RangeBounds + Clone + std::fmt::Debug) { + assert_eq!( + set.last_set_in(needle.clone()), + easy(set, needle.clone()), + "{:?} in {:?}", + needle, + set + ); + } + let mut set = IntervalSet::new(300); + cmp(&set, 50..=50); + set.insert(64); + cmp(&set, 64..=64); + set.insert(64 - 1); + cmp(&set, 0..=64 - 1); + cmp(&set, 0..=5); + cmp(&set, 10..100); + set.insert(100); + cmp(&set, 100..110); + cmp(&set, 99..100); + cmp(&set, 99..=100); + + for i in 0..=30 { + for j in i..=30 { + for k in 0..30 { + let mut set = IntervalSet::new(100); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + } + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/interval.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,269 @@ +use std::iter::Step; +use std::marker::PhantomData; +use std::ops::Bound; +use std::ops::RangeBounds; + +use crate::vec::Idx; +use crate::vec::IndexVec; +use smallvec::SmallVec; + +#[cfg(test)] +mod tests; + +/// Stores a set of intervals on the indices. +#[derive(Debug, Clone)] +pub struct IntervalSet { + // Start, end + map: SmallVec<[(u32, u32); 4]>, + domain: usize, + _data: PhantomData, +} + +#[inline] +fn inclusive_start(range: impl RangeBounds) -> u32 { + match range.start_bound() { + Bound::Included(start) => start.index() as u32, + Bound::Excluded(start) => start.index() as u32 + 1, + Bound::Unbounded => 0, + } +} + +#[inline] +fn inclusive_end(domain: usize, range: impl RangeBounds) -> Option { + let end = match range.end_bound() { + Bound::Included(end) => end.index() as u32, + Bound::Excluded(end) => end.index().checked_sub(1)? as u32, + Bound::Unbounded => domain.checked_sub(1)? as u32, + }; + Some(end) +} + +impl IntervalSet { + pub fn new(domain: usize) -> IntervalSet { + IntervalSet { map: SmallVec::new(), domain, _data: PhantomData } + } + + pub fn clear(&mut self) { + self.map.clear(); + } + + pub fn iter(&self) -> impl Iterator + '_ + where + I: Step, + { + self.iter_intervals().flatten() + } + + /// Iterates through intervals stored in the set, in order. + pub fn iter_intervals(&self) -> impl Iterator> + '_ + where + I: Step, + { + self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1)) + } + + /// Returns true if we increased the number of elements present. + pub fn insert(&mut self, point: I) -> bool { + self.insert_range(point..=point) + } + + /// Returns true if we increased the number of elements present. + pub fn insert_range(&mut self, range: impl RangeBounds + Clone) -> bool { + let start = inclusive_start(range.clone()); + let Some(mut end) = inclusive_end(self.domain, range) else { + // empty range + return false; + }; + if start > end { + return false; + } + + loop { + // This condition looks a bit weird, but actually makes sense. + // + // if r.0 == end + 1, then we're actually adjacent, so we want to + // continue to the next range. We're looking here for the first + // range which starts *non-adjacently* to our end. + let next = self.map.partition_point(|r| r.0 <= end + 1); + if let Some(last) = next.checked_sub(1) { + let (prev_start, prev_end) = &mut self.map[last]; + if *prev_end + 1 >= start { + // If the start for the inserted range is adjacent to the + // end of the previous, we can extend the previous range. + if start < *prev_start { + // Our range starts before the one we found. We'll need + // to *remove* it, and then try again. + // + // FIXME: This is not so efficient; we may need to + // recurse a bunch of times here. Instead, it's probably + // better to do something like drain_filter(...) on the + // map to be able to delete or modify all the ranges in + // start..=end and then potentially re-insert a new + // range. + end = std::cmp::max(end, *prev_end); + self.map.remove(last); + } else { + // We overlap with the previous range, increase it to + // include us. + // + // Make sure we're actually going to *increase* it though -- + // it may be that end is just inside the previously existing + // set. + return if end > *prev_end { + *prev_end = end; + true + } else { + false + }; + } + } else { + // Otherwise, we don't overlap, so just insert + self.map.insert(last + 1, (start, end)); + return true; + } + } else { + if self.map.is_empty() { + // Quite common in practice, and expensive to call memcpy + // with length zero. + self.map.push((start, end)); + } else { + self.map.insert(next, (start, end)); + } + return true; + } + } + } + + pub fn contains(&self, needle: I) -> bool { + let needle = needle.index() as u32; + let last = match self.map.partition_point(|r| r.0 <= needle).checked_sub(1) { + Some(idx) => idx, + None => { + // All ranges in the map start after the new range's end + return false; + } + }; + let (_, prev_end) = &self.map[last]; + needle <= *prev_end + } + + pub fn superset(&self, other: &IntervalSet) -> bool + where + I: Step, + { + // FIXME: Performance here is probably not great. We will be doing a lot + // of pointless tree traversals. + other.iter().all(|elem| self.contains(elem)) + } + + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Returns the maximum (last) element present in the set from `range`. + pub fn last_set_in(&self, range: impl RangeBounds + Clone) -> Option { + let start = inclusive_start(range.clone()); + let Some(end) = inclusive_end(self.domain, range) else { + // empty range + return None; + }; + if start > end { + return None; + } + let last = match self.map.partition_point(|r| r.0 <= end).checked_sub(1) { + Some(idx) => idx, + None => { + // All ranges in the map start after the new range's end + return None; + } + }; + let (_, prev_end) = &self.map[last]; + if start <= *prev_end { Some(I::new(std::cmp::min(*prev_end, end) as usize)) } else { None } + } + + pub fn insert_all(&mut self) { + self.clear(); + self.map.push((0, self.domain.try_into().unwrap())); + } + + pub fn union(&mut self, other: &IntervalSet) -> bool + where + I: Step, + { + assert_eq!(self.domain, other.domain); + let mut did_insert = false; + for range in other.iter_intervals() { + did_insert |= self.insert_range(range); + } + did_insert + } +} + +/// This data structure optimizes for cases where the stored bits in each row +/// are expected to be highly contiguous (long ranges of 1s or 0s), in contrast +/// to BitMatrix and SparseBitMatrix which are optimized for +/// "random"/non-contiguous bits and cheap(er) point queries at the expense of +/// memory usage. +#[derive(Clone)] +pub struct SparseIntervalMatrix +where + R: Idx, + C: Idx, +{ + rows: IndexVec>, + column_size: usize, +} + +impl SparseIntervalMatrix { + pub fn new(column_size: usize) -> SparseIntervalMatrix { + SparseIntervalMatrix { rows: IndexVec::new(), column_size } + } + + pub fn rows(&self) -> impl Iterator { + self.rows.indices() + } + + pub fn row(&self, row: R) -> Option<&IntervalSet> { + self.rows.get(row) + } + + fn ensure_row(&mut self, row: R) -> &mut IntervalSet { + self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size)); + &mut self.rows[row] + } + + pub fn union_row(&mut self, row: R, from: &IntervalSet) -> bool + where + C: Step, + { + self.ensure_row(row).union(from) + } + + pub fn union_rows(&mut self, read: R, write: R) -> bool + where + C: Step, + { + if read == write || self.rows.get(read).is_none() { + return false; + } + self.ensure_row(write); + let (read_row, write_row) = self.rows.pick2_mut(read, write); + write_row.union(read_row) + } + + pub fn insert_all_into_row(&mut self, row: R) { + self.ensure_row(row).insert_all(); + } + + pub fn insert_range(&mut self, row: R, range: impl RangeBounds + Clone) { + self.ensure_row(row).insert_range(range); + } + + pub fn insert(&mut self, row: R, point: C) -> bool { + self.ensure_row(row).insert(point) + } + + pub fn contains(&self, row: R, point: C) -> bool { + self.row(row).map_or(false, |r| r.contains(point)) + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,13 +1,13 @@ #![feature(allow_internal_unstable)] #![feature(bench_black_box)] #![feature(extend_one)] -#![feature(iter_zip)] #![feature(min_specialization)] #![feature(step_trait)] #![feature(test)] #![feature(let_else)] pub mod bit_set; +pub mod interval; pub mod vec; // FIXME(#56935): Work around ICEs during cross-compilation. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/vec.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/vec.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/vec.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_index/src/vec.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ /// Represents some newtyped `usize` wrapper. /// /// Purpose: avoid mixing indexes for different bitvector domains. -pub trait Idx: Copy + 'static + Ord + Debug + Hash { +pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash { fn new(idx: usize) -> Self; fn index(self) -> usize; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs 2022-02-23 04:07:21.000000000 +0000 @@ -134,7 +134,7 @@ /// response*, then we don't typically replace free regions, as they /// must have been introduced from other parts of the system. trait CanonicalizeRegionMode { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -146,7 +146,7 @@ struct CanonicalizeQueryResponse; impl CanonicalizeRegionMode for CanonicalizeQueryResponse { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -203,7 +203,7 @@ struct CanonicalizeUserTypeAnnotation; impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -226,7 +226,7 @@ struct CanonicalizeAllFreeRegions; impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -242,7 +242,7 @@ struct CanonicalizeFreeRegionsOtherThanStatic; impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/combine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/combine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/combine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/combine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -37,7 +37,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -533,7 +533,7 @@ needs_wf: bool, } -impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -572,8 +572,9 @@ // (e.g., #41849). relate::relate_substs(self, None, a_subst, b_subst) } else { - let opt_variances = self.tcx().variances_of(item_def_id); - relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst) + let tcx = self.tcx(); + let opt_variances = tcx.variances_of(item_def_id); + relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst) } } @@ -790,7 +791,7 @@ a_is_expected: bool, (a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>), ) -> TypeError<'tcx> { - TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a, b)) } fn int_unification_error<'tcx>( @@ -798,7 +799,7 @@ v: (ty::IntVarValue, ty::IntVarValue), ) -> TypeError<'tcx> { let (a, b) = v; - TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b)) } fn float_unification_error<'tcx>( @@ -806,7 +807,7 @@ v: (ty::FloatVarValue, ty::FloatVarValue), ) -> TypeError<'tcx> { let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; - TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } struct ConstInferUnifier<'cx, 'tcx> { @@ -827,7 +828,7 @@ // We use `TypeRelation` here to propagate `RelateResult` upwards. // // Both inputs are expected to be the same. -impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/equate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/equate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/equate.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/equate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ } } -impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Equate" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -83,7 +83,7 @@ pub mod nice_region_error; -pub(super) fn note_and_explain_region( +pub(super) fn note_and_explain_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, @@ -116,7 +116,7 @@ emit_msg_span(err, prefix, description, span, suffix); } -fn explain_free_region( +fn explain_free_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, @@ -128,7 +128,7 @@ label_msg_span(err, prefix, description, span, suffix); } -fn msg_span_from_free_region( +fn msg_span_from_free_region<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, alt_span: Option, @@ -145,7 +145,7 @@ } } -fn msg_span_from_early_bound_and_free_regions( +fn msg_span_from_early_bound_and_free_regions<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Span) { @@ -226,7 +226,7 @@ } } -pub fn unexpected_hidden_region_diagnostic( +pub fn unexpected_hidden_region_diagnostic<'tcx>( tcx: TyCtxt<'tcx>, span: Span, hidden_ty: Ty<'tcx>, @@ -275,7 +275,7 @@ fn_returns, hidden_region.to_string(), None, - format!("captures {}", hidden_region), + format!("captures `{}`", hidden_region), None, ) } @@ -316,7 +316,7 @@ /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. -pub fn same_type_modulo_infer(a: Ty<'tcx>, b: Ty<'ctx>) -> bool { +pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match (&a.kind(), &b.kind()) { (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { if did_a != did_b { @@ -384,6 +384,7 @@ sub_r, sup_origin, sup_r, + _, ) => { if sub_r.is_placeholder() { self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit(); @@ -464,7 +465,7 @@ errors.sort_by_key(|u| match *u { RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), + RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), }); errors @@ -603,7 +604,7 @@ exp_found: Option>>, terr: &TypeError<'tcx>, ) { - match cause.code { + match *cause.code() { ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { let ty = self.resolve_vars_if_possible(root_ty); if ty.is_suggestable() { @@ -780,7 +781,7 @@ } _ => { if let ObligationCauseCode::BindingObligation(_, binding_span) = - cause.code.peel_derives() + cause.code().peel_derives() { if matches!(terr, TypeError::RegionsPlaceholderMismatch) { err.span_note(*binding_span, "the lifetime requirement is introduced here"); @@ -1429,6 +1430,15 @@ } } + /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and + /// the return type of `async fn`s. + /// + /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`. + /// + /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using + /// the message in `secondary_span` as the primary label, and apply the message that would + /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on + /// E0271, like `src/test/ui/issues/issue-39970.stderr`. pub fn note_type_err( &self, diag: &mut DiagnosticBuilder<'tcx>, @@ -1436,6 +1446,7 @@ secondary_span: Option<(Span, String)>, mut values: Option>, terr: &TypeError<'tcx>, + swap_secondary_and_primary: bool, ) { let span = cause.span(self.tcx); debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr); @@ -1612,9 +1623,32 @@ match terr { TypeError::ObjectUnsafeCoercion(_) => {} _ => { - diag.span_label(span, terr.to_string()); + let mut label_or_note = |span: Span, msg: &str| { + if &[span] == diag.span.primary_spans() { + diag.span_label(span, msg); + } else { + diag.span_note(span, msg); + } + }; if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, msg); + if swap_secondary_and_primary { + let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound { + expected, + .. + })) = values + { + format!("expected this to be `{}`", expected) + } else { + terr.to_string() + }; + label_or_note(sp, &terr); + label_or_note(span, &msg); + } else { + label_or_note(span, &terr.to_string()); + label_or_note(sp, &msg); + } + } else { + label_or_note(span, &terr.to_string()); } } }; @@ -1695,10 +1729,10 @@ } _ => exp_found, }; - debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code); + debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code()); if let Some(exp_found) = exp_found { let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } = - &cause.code + cause.code() { // Skip if the root_ty of the pattern is not the same as the expected_ty. // If these types aren't equal then we've probably peeled off a layer of arrays. @@ -1793,7 +1827,7 @@ exp_span, exp_found.expected, exp_found.found, ); - if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code { + if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() { return; } @@ -1801,7 +1835,7 @@ self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.found), ) { - (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match &cause.code { + (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diag.multipart_suggestion( "consider `await`ing on both `Future`s", @@ -1841,7 +1875,7 @@ Applicability::MaybeIncorrect, ); } - (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code { + (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code() { ObligationCauseCode::Pattern { span: Some(span), .. } | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { diag.span_suggestion_verbose( @@ -1893,7 +1927,7 @@ .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs))) .find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found)) { - if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code { + if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let suggestion = if expected_def.is_struct() { format!("{}.{}", snippet, name) @@ -2007,11 +2041,11 @@ if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) = trace.values { - // If a tuple of length one was expected and the found expression has - // parentheses around it, perhaps the user meant to write `(expr,)` to - // build a tuple (issue #86100) match (expected.kind(), found.kind()) { (ty::Tuple(_), ty::Tuple(_)) => {} + // If a tuple of length one was expected and the found expression has + // parentheses around it, perhaps the user meant to write `(expr,)` to + // build a tuple (issue #86100) (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { if let Some(code) = @@ -2026,11 +2060,46 @@ } } } + // If a character was expected and the found expression is a string literal + // containing a single character, perhaps the user meant to write `'c'` to + // specify a character literal (issue #92479) + (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { + if let Some(code) = + code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) + { + if code.chars().nth(1).is_none() { + err.span_suggestion( + span, + "if you meant to write a `char` literal, use single quotes", + format!("'{}'", code), + Applicability::MachineApplicable, + ); + } + } + } + } + // If a string was expected and the found expression is a character literal, + // perhaps the user meant to write `"s"` to specify a string literal. + (ty::Ref(_, r, _), ty::Char) if r.is_str() => { + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { + if let Some(code) = + code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) + { + err.span_suggestion( + span, + "if you meant to write a `str` literal, use double quotes", + format!("\"{}\"", code), + Applicability::MachineApplicable, + ); + } + } + } _ => {} } } if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = - trace.cause.code + *trace.cause.code() { if let hir::MatchSource::TryDesugar = source { if let Some((expected_ty, found_ty)) = self.values_str(trace.values) { @@ -2048,7 +2117,7 @@ struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str) } }; - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); diag } @@ -2218,8 +2287,7 @@ .map(|p| p.name.as_str()), ); } - let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); - possible.find(|candidate| !lts.contains(&candidate.as_str())) + possible.find(|candidate| !lts_names.contains(&&candidate[..])) }) .unwrap_or("'lt".to_string()); let add_lt_sugg = generics @@ -2626,7 +2694,7 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; - match self.code { + match self.code() { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => { @@ -2661,7 +2729,7 @@ fn as_requirement_str(&self) -> &'static str { use crate::traits::ObligationCauseCode::*; - match self.code { + match self.code() { CompareImplMethodObligation { .. } => "method type is compatible with trait", CompareImplTypeObligation { .. } => "associated type is compatible with trait", ExprAssignable => "expression is assignable", diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,5 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::InferCtxt; +use crate::infer::{InferCtxt, Symbol}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -10,7 +10,7 @@ use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -305,6 +305,15 @@ Const { is_parameter: bool }, } +impl UnderspecifiedArgKind { + fn descr(&self) -> &'static str { + match self { + Self::Type { .. } => "type", + Self::Const { .. } => "const", + } + } +} + impl InferenceDiagnosticsData { /// Generate a label for a generic argument which can't be inferred. When not /// much is known about the argument, `use_diag` may be used to describe the @@ -400,36 +409,75 @@ } } GenericArgKind::Const(ct) => { - if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { - let origin = - self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; - if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = - origin.kind - { - return InferenceDiagnosticsData { - name: name.to_string(), + match ct.val { + ty::ConstKind::Infer(InferConst::Var(vid)) => { + let origin = self + .inner + .borrow_mut() + .const_unification_table() + .probe_value(vid) + .origin; + if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = + origin.kind + { + return InferenceDiagnosticsData { + name: name.to_string(), + span: Some(origin.span), + kind: UnderspecifiedArgKind::Const { is_parameter: true }, + parent: InferenceDiagnosticsParentData::for_def_id( + self.tcx, def_id, + ), + }; + } + + debug_assert!(!origin.span.is_dummy()); + let mut s = String::new(); + let mut printer = + ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + let _ = ct.print(printer); + InferenceDiagnosticsData { + name: s, span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: true }, - parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id), - }; + kind: UnderspecifiedArgKind::Const { is_parameter: false }, + parent: None, + } } - - debug_assert!(!origin.span.is_dummy()); - let mut s = String::new(); - let mut printer = - ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); - if let Some(highlight) = highlight { - printer.region_highlight_mode = highlight; + ty::ConstKind::Unevaluated(ty::Unevaluated { + substs_: Some(substs), .. + }) => { + assert!(substs.has_infer_types_or_consts()); + + // FIXME: We only use the first inference variable we encounter in + // `substs` here, this gives insufficiently informative diagnostics + // in case there are multiple inference variables + for s in substs.iter() { + match s.unpack() { + GenericArgKind::Type(t) => match t.kind() { + ty::Infer(_) => { + return self.extract_inference_diagnostics_data(s, None); + } + _ => {} + }, + GenericArgKind::Const(c) => match c.val { + ty::ConstKind::Infer(InferConst::Var(_)) => { + return self.extract_inference_diagnostics_data(s, None); + } + _ => {} + }, + _ => {} + } + } + bug!( + "expected an inference variable in substs of unevaluated const {:?}", + ct + ); } - let _ = ct.print(printer); - InferenceDiagnosticsData { - name: s, - span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: false }, - parent: None, + _ => { + bug!("unexpect const: {:?}", ct); } - } else { - bug!("unexpect const: {:?}", ct); } } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), @@ -548,6 +596,7 @@ } } + let param_type = arg_data.kind.descr(); let suffix = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { let substs = @@ -586,13 +635,15 @@ } Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { let ty = ty_to_string(ty); - format!("the explicit type `{}`, with the type parameters specified", ty) + format!("the explicit type `{}`, with the {} parameters specified", ty, param_type) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { + let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); + let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); let ty = ty_to_string(ty); format!( - "the explicit type `{}`, where the type parameter `{}` is specified", - ty, arg_data.name, + "the explicit type `{}`, where the {} parameter `{}` is specified", + ty, param_type, arg_data.name, ) } _ => "a type".to_string(), @@ -868,3 +919,117 @@ err } } + +/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After +/// performing that replacement, we'll turn all remaining infer type params to use their name from +/// their definition, and replace all the `[type error]`s back to being infer so they display in +/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params +/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could +/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. +struct ResolvedTypeParamEraser<'tcx> { + tcx: TyCtxt<'tcx>, + level: usize, +} + +impl<'tcx> ResolvedTypeParamEraser<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + ResolvedTypeParamEraser { tcx, level: 0 } + } + + /// Replace not yet inferred const params with their def name. + fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> { + match c.val { + ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty), + _ => c, + } + } +} + +impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + self.level += 1; + let t = match t.kind() { + // We'll hide this type only if all its type params are hidden as well. + ty::Adt(def, substs) => { + let generics = self.tcx().generics_of(def.did); + // Account for params with default values, like `Vec`, where we + // want to show `Vec`, not `Vec`. If we replaced that + // subst, then we'd get the incorrect output, so we passthrough. + let substs: Vec<_> = substs + .iter() + .zip(generics.params.iter()) + .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { + (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, + (crate::infer::GenericArgKind::Const(c), _) => { + self.replace_infers(c, param.index, param.name).into() + } + _ => subst.super_fold_with(self), + }) + .collect(); + let should_keep = |subst: &GenericArg<'_>| match subst.unpack() { + ty::subst::GenericArgKind::Type(t) => match t.kind() { + ty::Error(_) => false, + _ => true, + }, + // Account for `const` params here, otherwise `doesnt_infer.rs` + // shows `_` instead of `Foo<{ _: u32 }>` + ty::subst::GenericArgKind::Const(_) => true, + _ => false, + }; + if self.level == 1 || substs.iter().any(should_keep) { + let substs = self.tcx().intern_substs(&substs[..]); + self.tcx().mk_ty(ty::Adt(def, substs)) + } else { + self.tcx().ty_error() + } + } + ty::Ref(_, ty, _) => { + let ty = self.fold_ty(ty); + match ty.kind() { + // Avoid `&_`, these can be safely presented as `_`. + ty::Error(_) => self.tcx().ty_error(), + _ => t.super_fold_with(self), + } + } + // We could account for `()` if we wanted to replace it, but it's assured to be short. + ty::Tuple(_) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Opaque(..) + | ty::Projection(_) + | ty::Never => t.super_fold_with(self), + ty::Array(ty, c) => self + .tcx() + .mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))), + // We don't want to hide type params that haven't been resolved yet. + // This would be the type that will be written out with the type param + // name in the output. + ty::Infer(_) => t, + // We don't want to hide the outermost type, only its type params. + _ if self.level == 1 => t.super_fold_with(self), + // Hide this type + _ => self.tcx().ty_error(), + }; + self.level -= 1; + t + } +} + +/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. +struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); +impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.0 + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind() { + ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), + _ => t.super_fold_with(self), + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,7 +20,7 @@ /// ``` /// The function returns the nested type corresponding to the anonymous region /// for e.g., `&u8` and `Vec<&u8>`. -pub(crate) fn find_anon_type( +pub(crate) fn find_anon_type<'tcx>( tcx: TyCtxt<'tcx>, region: Region<'tcx>, br: &ty::BoundRegionKind, @@ -50,7 +50,7 @@ // This method creates a FindNestedTypeVisitor which returns the type corresponding // to the anonymous region. -fn find_component_for_bound_region( +fn find_component_for_bound_region<'tcx>( tcx: TyCtxt<'tcx>, arg: &'tcx hir::Ty<'tcx>, br: &ty::BoundRegionKind, @@ -83,7 +83,7 @@ current_index: ty::DebruijnIndex, } -impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -207,7 +207,7 @@ current_index: ty::DebruijnIndex, } -impl Visitor<'tcx> for TyPathVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,15 +31,15 @@ }; // If we added a "points at argument expression" obligation, we remove it here, we care // about the original obligation only. - let code = match &cause.code { + let code = match cause.code() { ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code, - _ => &cause.code, + _ => cause.code(), }; let (parent, impl_def_id) = match code { ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), _ => return None, }; - let binding_span = match parent.code { + let binding_span = match *parent.code() { ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, _ => return None, }; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -67,7 +67,7 @@ pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { match (&self.error, self.regions) { (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)), - (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => { + (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => { Some((origin.span(), sub, sup)) } (None, Some((span, sub, sup))) => Some((span, sub, sup)), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,7 +13,7 @@ use std::fmt::{self, Write}; -impl NiceRegionError<'me, 'tcx> { +impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. pub(super) fn try_report_placeholder_conflict(&self) -> Option> { @@ -34,6 +34,7 @@ sub_placeholder @ ty::RePlaceholder(_), _, sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -49,6 +50,7 @@ sub_placeholder @ ty::RePlaceholder(_), _, _, + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -64,6 +66,7 @@ _, _, sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -79,6 +82,7 @@ _, SubregionOrigin::Subtype(box TypeTrace { cause, values }), sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -204,7 +208,7 @@ ); let mut err = self.tcx().sess.struct_span_err(span, &msg); - let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code { + let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = *cause.code() { err.span_label(span, "doesn't satisfy where-clause"); err.span_label( self.tcx().def_span(def_id), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,8 @@ use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_middle::ty::{ - self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor, + self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable, + TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::{MultiSpan, Span}; @@ -23,7 +24,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); let tcx = self.tcx(); - let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? { + let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? { RegionResolutionError::SubSupConflict( _, var_origin, @@ -31,8 +32,9 @@ sub_r, sup_origin, sup_r, + spans, ) if **sub_r == RegionKind::ReStatic => { - (var_origin, sub_origin, sub_r, sup_origin, sup_r) + (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) } RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(box TypeTrace { cause, .. }), @@ -40,7 +42,7 @@ sup_r, ) if **sub_r == RegionKind::ReStatic => { // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. - if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { // This may have a closure and it would cause ICE // through `find_param_with_region` (#78262). let anon_reg_sup = tcx.is_suitable_region(sup_r)?; @@ -74,7 +76,7 @@ err.span_label( cause.span, &format!( - "...is captured and required to live as long as `'static` here \ + "...is used and required to live as long as `'static` here \ because of an implicit lifetime bound on the {}", match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => @@ -123,63 +125,108 @@ param_name, lifetime, ); - err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); - debug!("try_report_static_impl_trait: param_info={:?}", param); - // We try to make the output have fewer overlapping spans if possible. - if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) - && sup_origin.span() != return_sp - { - // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` - - // Customize the spans and labels depending on their relative order so - // that split sentences flow correctly. - if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { - // Avoid the following: + let (mention_influencer, influencer_point) = + if sup_origin.span().overlaps(param.param_ty_span) { + // Account for `async fn` like in `async-await/issues/issue-62097.rs`. + // The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same + // place (but with different `ctxt`, hence `overlaps` instead of `==` above). // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ---------^- + // This avoids the following: // - // and instead show: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ - err.span_label( - sup_origin.span(), - "...is captured here, requiring it to live as long as `'static`", - ); + // LL | pub async fn run_dummy_fn(&self) { + // | ^^^^^ + // | | + // | this data with an anonymous lifetime `'_`... + // | ...is captured here... + (false, sup_origin.span()) } else { - err.span_label(sup_origin.span(), "...is captured here..."); - if return_sp < sup_origin.span() { - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", + (!sup_origin.span().overlaps(return_sp), param.param_ty_span) + }; + err.span_label(influencer_point, &format!("this data with {}...", lifetime)); + + debug!("try_report_static_impl_trait: param_info={:?}", param); + + let mut spans = spans.clone(); + + if mention_influencer { + spans.push(sup_origin.span()); + } + // We dedup the spans *ignoring* expansion context. + spans.sort(); + spans.dedup_by_key(|span| (span.lo(), span.hi())); + + // We try to make the output have fewer overlapping spans if possible. + let require_msg = if spans.is_empty() { + "...is used and required to live as long as `'static` here" + } else { + "...and is required to live as long as `'static` here" + }; + let require_span = + if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp }; + + for span in &spans { + err.span_label(*span, "...is used here..."); + } + + if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) { + // If any of the "captured here" labels appears on the same line or after + // `require_span`, we put it on a note to ensure the text flows by appearing + // always at the end. + err.span_note(require_span, require_msg); + } else { + // We don't need a note, it's already at the end, it can be shown as a `span_label`. + err.span_label(require_span, require_msg); + } + + if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { + err.span_note(*bound, "`'static` lifetime requirement introduced by this bound"); + } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { + if let ObligationCauseCode::ReturnValue(hir_id) + | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() + { + let parent_id = tcx.hir().get_parent_item(*hir_id); + if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { + let mut span: MultiSpan = fn_decl.output.span().into(); + let mut add_label = true; + if let hir::FnRetTy::Return(ty) = fn_decl.output { + let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); + v.visit_ty(ty); + if !v.0.is_empty() { + span = v.0.clone().into(); + for sp in v.0 { + span.push_span_label( + sp, + "`'static` requirement introduced here".to_string(), + ); + } + add_label = false; + } + } + if add_label { + span.push_span_label( + fn_decl.output.span(), + "requirement introduced by this return type".to_string(), + ); + } + span.push_span_label( + cause.span, + "because of this returned expression".to_string(), ); - } else { - err.span_label( - return_sp, - "...and is required to live as long as `'static` here", + err.span_note( + span, + "`'static` lifetime requirement introduced by the return type", ); } } - } else { - err.span_label( - return_sp, - "...is captured and required to live as long as `'static` here", - ); } let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let mut override_error_code = None; if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a // `'static` lifetime when called as a method on a binding: `bar.qux()`. if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { @@ -188,9 +235,9 @@ } } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { - let code = match &cause.code { - ObligationCauseCode::MatchImpl(parent, ..) => &parent.code, - _ => &cause.code, + let code = match cause.code() { + ObligationCauseCode::MatchImpl(parent, ..) => parent.code(), + _ => cause.code(), }; if let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code) @@ -240,7 +287,7 @@ } pub fn suggest_new_region_bound( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, err: &mut DiagnosticBuilder<'_>, fn_returns: Vec<&rustc_hir::Ty<'_>>, lifetime_name: String, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs 2022-02-23 04:07:21.000000000 +0000 @@ -28,6 +28,7 @@ _sub, sup_origin, _sup, + _, ) = error.clone() { if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { @@ -35,7 +36,7 @@ ValuePairs::Types(sub_expected_found), ValuePairs::Types(sup_expected_found), CompareImplMethodObligation { trait_item_def_id, .. }, - ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) + ) = (&sub_trace.values, &sup_trace.values, sub_trace.cause.code()) { if sup_expected_found == sub_expected_found { self.emit_err( @@ -85,7 +86,7 @@ counter: usize, } - impl HighlightBuilder<'tcx> { + impl<'tcx> HighlightBuilder<'tcx> { fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode { let mut builder = HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx }; @@ -185,7 +186,7 @@ types: Vec, } -impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { type Map = rustc_middle::hir::map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -107,7 +107,7 @@ kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }), .. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/note.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/note.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/note.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/error_reporting/note.rs 2022-02-23 04:07:21.000000000 +0000 @@ -359,13 +359,13 @@ match placeholder_origin { infer::Subtype(box ref trace) if matches!( - &trace.cause.code.peel_derives(), + &trace.cause.code().peel_derives(), ObligationCauseCode::BindingObligation(..) ) => { // Hack to get around the borrow checker because trace.cause has an `Rc`. if let ObligationCauseCode::BindingObligation(_, span) = - &trace.cause.code.peel_derives() + &trace.cause.code().peel_derives() { let span = *span; let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/free_regions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/free_regions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/free_regions.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/free_regions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ /// /// This stuff is a bit convoluted and should be refactored, but as we /// transition to NLL, it'll all go away anyhow. -pub struct RegionRelations<'a, 'tcx> { +pub(crate) struct RegionRelations<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, /// The context used for debug messages diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/glb.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/glb.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/glb.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/glb.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ } } -impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Glb" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -19,6 +19,7 @@ use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{Region, RegionVid}; +use rustc_span::Span; use std::fmt; /// This function performs lexical region resolution given a complete @@ -27,7 +28,7 @@ /// assuming such values can be found. It returns the final values of /// all the variables as well as a set of errors that must be reported. #[instrument(level = "debug", skip(region_rels, var_infos, data))] -pub fn resolve<'tcx>( +pub(crate) fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, @@ -96,6 +97,7 @@ Region<'tcx>, SubregionOrigin<'tcx>, Region<'tcx>, + Vec, // All the influences on a given value that didn't meet its constraints. ), /// Indicates a `'b: 'a` constraint where `'a` is in a universe that @@ -567,7 +569,30 @@ // if this rule starts to create problems we'll // have to revisit this portion of the code and // think hard about it. =) -- nikomatsakis - self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors); + + // Obtain the spans for all the places that can + // influence the constraints on this value for + // richer diagnostics in `static_impl_trait`. + let influences: Vec = self + .data + .constraints + .iter() + .filter_map(|(constraint, origin)| match (constraint, origin) { + ( + Constraint::VarSubVar(_, sup), + SubregionOrigin::DataBorrowed(_, sp), + ) if sup == &node_vid => Some(*sp), + _ => None, + }) + .collect(); + + self.collect_error_for_expanding_node( + graph, + &mut dup_vec, + node_vid, + errors, + influences, + ); } } } @@ -621,6 +646,7 @@ dup_vec: &mut IndexVec>, node_idx: RegionVid, errors: &mut Vec>, + influences: Vec, ) { // Errors in expanding nodes result from a lower-bound that is // not contained by an upper-bound. @@ -667,6 +693,7 @@ sup: {:?}", origin, node_idx, lower_bound.region, upper_bound.region ); + errors.push(RegionResolutionError::SubSupConflict( node_idx, origin, @@ -674,6 +701,7 @@ lower_bound.region, upper_bound.origin.clone(), upper_bound.region, + influences, )); return; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lub.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lub.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lub.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/lub.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,7 +23,7 @@ } } -impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Lub" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,6 +21,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::EvalToConstValueResult; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -553,7 +554,7 @@ fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; } -impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { +impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, @@ -1584,13 +1585,27 @@ unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - let mut original_values = OriginalQueryValues::default(); - let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values); + let mut substs = unevaluated.substs(self.tcx); + substs = self.resolve_vars_if_possible(substs); + + // Postpone the evaluation of constants whose substs depend on inference + // variables + if substs.has_infer_types_or_consts() { + return Err(ErrorHandled::TooGeneric); + } + + let param_env_erased = self.tcx.erase_regions(param_env); + let substs_erased = self.tcx.erase_regions(substs); + + let unevaluated = ty::Unevaluated { + def: unevaluated.def, + substs_: Some(substs_erased), + promoted: unevaluated.promoted, + }; - let (param_env, unevaluated) = canonical.value; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env, unevaluated, span) + self.tcx.const_eval_resolve(param_env_erased, unevaluated, span) } /// If `typ` is a type variable of some kind, resolve it one level @@ -1703,7 +1718,7 @@ Const(ConstVid<'tcx>), } -impl TyOrConstInferVar<'tcx> { +impl<'tcx> TyOrConstInferVar<'tcx> { /// Tries to extract an inference variable from a type or a constant, returns `None` /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). @@ -1809,7 +1824,7 @@ where F: FnOnce() -> Self, { - match cause.code { + match *cause.code() { traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => { SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -407,7 +407,7 @@ /// Extract the scopes that apply to whichever side of the tuple /// the vid was found on. See the comment where this is called /// for more details on why we want them. - fn vid_scopes>( + fn vid_scopes<'r, D: TypeRelatingDelegate<'tcx>>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec>; @@ -424,7 +424,7 @@ D: TypeRelatingDelegate<'tcx>; } -impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { +impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { fn vid(&self) -> ty::TyVid { self.0 } @@ -433,7 +433,7 @@ self.1 } - fn vid_scopes( + fn vid_scopes<'r, D>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec> @@ -456,7 +456,7 @@ } // In this case, the "vid" is the "b" type. -impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { +impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { fn vid(&self) -> ty::TyVid { self.1 } @@ -465,7 +465,7 @@ self.0 } - fn vid_scopes( + fn vid_scopes<'r, D>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec> @@ -487,7 +487,7 @@ } } -impl TypeRelation<'tcx> for TypeRelating<'me, 'tcx, D> +impl<'tcx, D> TypeRelation<'tcx> for TypeRelating<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { @@ -841,7 +841,7 @@ universe: ty::UniverseIndex, } -impl TypeRelation<'tcx> for TypeGeneralizer<'me, 'tcx, D> +impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/opaque_types.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/opaque_types.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/opaque_types.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/opaque_types.rs 2022-02-23 04:07:21.000000000 +0000 @@ -276,7 +276,7 @@ debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -461,33 +461,29 @@ if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.infcx.defining_use_anchor; - let def_scope_default = || { - let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) + let item_kind = &tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { + span_bug!( + self.value_span, + "weird opaque type: {:#?}, {:#?}", + ty.kind(), + item_kind + ) + }; + let in_definition_scope = match *origin { + // Async `impl Trait` + hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, + // Anonymous `impl Trait` + hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, + // Named `type Foo = impl Bar;` + hir::OpaqueTyOrigin::TyAlias => { + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) + } }; - let (in_definition_scope, origin) = - match tcx.hir().expect_item(opaque_hir_id).kind { - // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), - // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => ( - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), - origin, - ), - _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), - }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); + return self.fold_opaque_ty(ty, opaque_type_key, *origin); } debug!( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/components.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/components.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/components.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/components.rs 2022-02-23 04:07:21.000000000 +0000 @@ -49,7 +49,7 @@ /// Push onto `out` all the things that must outlive `'a` for the condition /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. -pub fn push_outlives_components( +pub fn push_outlives_components<'tcx>( tcx: TyCtxt<'tcx>, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, @@ -59,7 +59,7 @@ debug!("components({:?}) = {:?}", ty0, out); } -fn compute_components( +fn compute_components<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, @@ -190,7 +190,7 @@ } } -fn compute_components_recursive( +fn compute_components_recursive<'tcx>( tcx: TyCtxt<'tcx>, parent: GenericArg<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs 2022-02-23 04:07:21.000000000 +0000 @@ -102,7 +102,7 @@ infer::RelateParamBound( cause.span, sup_type, - match cause.code.peel_derives() { + match cause.code().peel_derives() { ObligationCauseCode::BindingObligation(_, span) => Some(*span), _ => None, }, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -65,7 +65,7 @@ undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } -impl std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { +impl<'tcx> std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { type Target = RegionConstraintStorage<'tcx>; #[inline] fn deref(&self) -> &RegionConstraintStorage<'tcx> { @@ -73,7 +73,7 @@ } } -impl std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { +impl<'tcx> std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { #[inline] fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> { self.storage diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/resolve.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/resolve.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/resolve.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/resolve.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; use rustc_middle::mir; -use rustc_middle::ty::fold::{TypeFolder, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; use std::ops::ControlFlow; @@ -175,81 +175,72 @@ where T: TypeFoldable<'tcx>, { - let mut full_resolver = FullTypeResolver { infcx, err: None }; - let result = value.fold_with(&mut full_resolver); - match full_resolver.err { - None => Ok(result), - Some(e) => Err(e), - } + value.try_fold_with(&mut FullTypeResolver { infcx }) } // N.B. This type is not public because the protocol around checking the // `err` field is not enforceable otherwise. struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - err: Option>, } impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { + type Error = FixupError<'tcx>; + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } +} - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { +impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { if !t.needs_infer() { - t // micro-optimize -- if there is nothing in this type that this fold affects... + Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t = self.infcx.shallow_resolve(t); match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { - self.err = Some(FixupError::UnresolvedTy(vid)); - self.tcx().ty_error() - } - ty::Infer(ty::IntVar(vid)) => { - self.err = Some(FixupError::UnresolvedIntTy(vid)); - self.tcx().ty_error() - } - ty::Infer(ty::FloatVar(vid)) => { - self.err = Some(FixupError::UnresolvedFloatTy(vid)); - self.tcx().ty_error() - } + ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)), + ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)), + ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)), ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } - _ => t.super_fold_with(self), + _ => t.try_super_fold_with(self), } } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { match *r { - ty::ReVar(rid) => self + ty::ReVar(rid) => Ok(self .infcx .lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") - .resolve_var(rid), - _ => r, + .resolve_var(rid)), + _ => Ok(r), } } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if !c.needs_infer() { - c // micro-optimize -- if there is nothing in this const that this fold affects... + Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects... } else { let c = self.infcx.shallow_resolve(c); match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { - self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().const_error(c.ty); + return Err(FixupError::UnresolvedConst(vid)); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); } _ => {} } - c.super_fold_with(self) + c.try_super_fold_with(self) } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/sub.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/sub.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/sub.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/infer/sub.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ } } -impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Sub" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,10 +17,8 @@ #![feature(box_patterns)] #![feature(derive_default_enum)] #![feature(extend_one)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(never_type)] -#![feature(in_band_lifetimes)] #![feature(control_flow_enum)] #![feature(min_specialization)] #![feature(label_break_value)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/engine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/engine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/engine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/engine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,9 +1,8 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty}; use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; @@ -48,26 +47,9 @@ fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - fn select_all_with_constness_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_all_or_error(infcx) - } - fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_where_possible(infcx) - } - fn pending_obligations(&self) -> Vec>; fn relationships(&mut self) -> &mut FxHashMap; @@ -81,7 +63,7 @@ ); } -impl> TraitEngineExt<'tcx> for T { +impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'_, 'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -35,7 +35,7 @@ } } -pub fn report_object_safety_error( +pub fn report_object_safety_error<'tcx>( tcx: TyCtxt<'tcx>, span: Span, trait_def_id: DefId, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -55,7 +55,7 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; -impl PredicateObligation<'tcx> { +impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. /// /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. @@ -69,9 +69,19 @@ } } +impl TraitObligation<'_> { + /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. + pub fn is_const(&self) -> bool { + match (self.predicate.skip_binder().constness, self.param_env.constness()) { + (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true, + _ => false, + } + } +} + // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateObligation<'_>, 32); +static_assert_size!(PredicateObligation<'_>, 48); pub type PredicateObligations<'tcx> = Vec>; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/project.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/project.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/project.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/project.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ }; use rustc_middle::ty::{self, Ty}; -pub use rustc_middle::traits::Reveal; +pub use rustc_middle::traits::{EvaluationResult, Reveal}; pub(crate) type UndoLog<'tcx> = snapshot_map::UndoLog, ProjectionCacheEntry<'tcx>>; @@ -80,7 +80,7 @@ ty: ty::ProjectionTy<'tcx>, } -impl ProjectionCacheKey<'tcx> { +impl<'tcx> ProjectionCacheKey<'tcx> { pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self { Self { ty } } @@ -92,7 +92,42 @@ Ambiguous, Recur, Error, - NormalizedTy(NormalizedTy<'tcx>), + NormalizedTy { + ty: NormalizedTy<'tcx>, + /// If we were able to successfully evaluate the + /// corresponding cache entry key during predicate + /// evaluation, then this field stores the final + /// result obtained from evaluating all of the projection + /// sub-obligations. During evaluation, we will skip + /// evaluating the cached sub-obligations in `ty` + /// if this field is set. Evaluation only + /// cares about the final result, so we don't + /// care about any region constraint side-effects + /// produced by evaluating the sub-boligations. + /// + /// Additionally, we will clear out the sub-obligations + /// entirely if we ever evaluate the cache entry (along + /// with all its sub obligations) to `EvaluatedToOk`. + /// This affects all users of the cache, not just evaluation. + /// Since a result of `EvaluatedToOk` means that there were + /// no region obligations that need to be tracked, it's + /// fine to forget about the sub-obligations - they + /// don't provide any additional information. However, + /// we do *not* discard any obligations when we see + /// `EvaluatedToOkModuloRegions` - we don't know + /// which sub-obligations may introduce region constraints, + /// so we keep them all to be safe. + /// + /// When we are not performing evaluation + /// (e.g. in `FulfillmentContext`), we ignore this field, + /// and always re-process the cached sub-obligations + /// (which may have been cleared out - see the above + /// paragraph). + /// This ensures that we do not lose any regions + /// constraints that arise from processing the + /// sub-obligations. + complete: Option, + }, } impl<'tcx> ProjectionCacheStorage<'tcx> { @@ -149,10 +184,41 @@ debug!("Not overwriting Recur"); return; } - let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value)); + let fresh_key = + map.insert(key, ProjectionCacheEntry::NormalizedTy { ty: value, complete: None }); assert!(!fresh_key, "never started projecting `{:?}`", key); } + /// Mark the relevant projection cache key as having its derived obligations + /// complete, so they won't have to be re-computed (this is OK to do in a + /// snapshot - if the snapshot is rolled back, the obligations will be + /// marked as incomplete again). + pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>, result: EvaluationResult) { + let mut map = self.map(); + match map.get(&key) { + Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => { + info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); + let mut ty = ty.clone(); + if result == EvaluationResult::EvaluatedToOk { + ty.obligations = vec![]; + } + map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) }); + } + ref value => { + // Type inference could "strand behind" old cache entries. Leave + // them alone for now. + info!("ProjectionCacheEntry::complete({:?}) - ignoring {:?}", key, value); + } + }; + } + + pub fn is_complete(&mut self, key: ProjectionCacheKey<'tcx>) -> Option { + self.map().get(&key).and_then(|res| match res { + ProjectionCacheEntry::NormalizedTy { ty: _, complete } => *complete, + _ => None, + }) + } + /// Indicates that trying to normalize `key` resulted in /// ambiguity. No point in trying it again then until we gain more /// type information (in which case, the "fully resolved" key will diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/structural_impls.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/structural_impls.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/structural_impls.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/structural_impls.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ use crate::traits; use crate::traits::project::Normalized; use rustc_middle::ty; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use std::fmt; use std::ops::ControlFlow; @@ -60,13 +60,16 @@ // TypeFoldable implementations. impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { - fn super_fold_with>(self, folder: &mut F) -> Self { - traits::Obligation { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(traits::Obligation { cause: self.cause, recursion_depth: self.recursion_depth, - predicate: self.predicate.fold_with(folder), - param_env: self.param_env.fold_with(folder), - } + predicate: self.predicate.try_fold_with(folder)?, + param_env: self.param_env.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_infer/src/traits/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,7 @@ use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -20,7 +20,7 @@ set: FxHashSet>, } -impl PredicateSet<'tcx> { +impl<'tcx> PredicateSet<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { Self { tcx, set: Default::default() } } @@ -40,7 +40,7 @@ } } -impl Extend> for PredicateSet<'tcx> { +impl<'tcx> Extend> for PredicateSet<'tcx> { fn extend>>(&mut self, iter: I) { for pred in iter { self.insert(pred); @@ -131,7 +131,7 @@ Obligation { cause, param_env, recursion_depth: 0, predicate } } -impl Elaborator<'tcx> { +impl<'tcx> Elaborator<'tcx> { pub fn filter_to_traits(self) -> FilterToTraits { FilterToTraits::new(self) } @@ -267,7 +267,7 @@ } } -impl Iterator for Elaborator<'tcx> { +impl<'tcx> Iterator for Elaborator<'tcx> { type Item = PredicateObligation<'tcx>; fn size_hint(&self) -> (usize, Option) { @@ -328,8 +328,8 @@ )); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); - if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { - stack.push(binder.value); + if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { + stack.push(binder.map_bound(|t| t.trait_ref)); } } @@ -362,8 +362,8 @@ fn next(&mut self) -> Option> { while let Some(obligation) = self.base_iterator.next() { - if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { - return Some(data.value); + if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() { + return Some(data.map_bound(|t| t.trait_ref)); } } None diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -8,6 +8,7 @@ [dependencies] libc = "0.2" +libloading = "0.7.1" tracing = "0.1" rustc-rayon-core = "0.3.1" rayon = { version = "0.3.1", package = "rustc-rayon" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/interface.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/interface.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/interface.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/interface.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ use rustc_errors::{ErrorReported, Handler}; use rustc_lint::LintStore; use rustc_middle::ty; -use rustc_parse::new_parser_from_source_str; +use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc_session::early_error; @@ -91,7 +91,6 @@ s ))); let filename = FileName::cfg_spec_source_code(&s); - let mut parser = new_parser_from_source_str(&sess, filename, s.to_string()); macro_rules! error { ($reason: expr) => { @@ -102,26 +101,27 @@ }; } - match &mut parser.parse_meta_item() { - Ok(meta_item) if parser.token == token::Eof => { - if meta_item.path.segments.len() != 1 { - error!("argument key must be an identifier"); - } - match &meta_item.kind { - MetaItemKind::List(..) => { - error!(r#"expected `key` or `key="value"`"#); - } - MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { - error!("argument value must be a string"); + match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(mut parser) => match &mut parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => { + if meta_item.path.segments.len() != 1 { + error!("argument key must be an identifier"); } - MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let ident = meta_item.ident().expect("multi-segment cfg key"); - return (ident.name, meta_item.value_str()); + match &meta_item.kind { + MetaItemKind::List(..) => {} + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { + error!("argument value must be a string"); + } + MetaItemKind::NameValue(..) | MetaItemKind::Word => { + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); + } } } - } - Ok(..) => {} - Err(err) => err.cancel(), + Ok(..) => {} + Err(err) => err.cancel(), + }, + Err(errs) => errs.into_iter().for_each(|mut err| err.cancel()), } error!(r#"expected `key` or `key="value"`"#); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/passes.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/passes.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/passes.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/passes.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,14 +3,14 @@ use crate::util; use rustc_ast::mut_visit::MutVisitor; -use rustc_ast::{self as ast, visit}; +use rustc_ast::{self as ast, visit, DUMMY_NODE_ID}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{ErrorReported, PResult}; +use rustc_errors::{Applicability, ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; @@ -323,8 +323,8 @@ let crate_attrs = krate.attrs.clone(); let extern_mod_loaded = |ident: Ident, attrs, items, span| { - let krate = ast::Crate { attrs, items, span }; - pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str()); + let krate = ast::Crate { attrs, items, span, id: DUMMY_NODE_ID, is_placeholder: false }; + pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, ident.name.as_str()); (krate.attrs, krate.items) }; let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded)); @@ -456,10 +456,26 @@ identifiers.sort_by_key(|&(key, _)| key); for (ident, mut spans) in identifiers.into_iter() { spans.sort(); - sess.diagnostic().span_err( - MultiSpan::from(spans), - &format!("identifiers cannot contain emoji: `{}`", ident), - ); + if ident == sym::ferris { + let first_span = spans[0]; + sess.diagnostic() + .struct_span_err( + MultiSpan::from(spans), + "Ferris cannot be used as an identifier", + ) + .span_suggestion( + first_span, + "try using their name instead", + "ferris".to_string(), + Applicability::MaybeIncorrect, + ) + .emit(); + } else { + sess.diagnostic().span_err( + MultiSpan::from(spans), + &format!("identifiers cannot contain emoji: `{}`", ident), + ); + } } }); @@ -568,7 +584,7 @@ fn escape_dep_filename(filename: &str) -> String { // Apparently clang and gcc *only* escape spaces: // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 - filename.replace(" ", "\\ ") + filename.replace(' ', "\\ ") } // Makefile comments only need escaping newlines and `\`. @@ -615,7 +631,7 @@ // (e.g. accessed in proc macros). let file_depinfo = sess.parse_sess.file_depinfo.borrow(); let extra_tracked_files = file_depinfo.iter().map(|path_sym| { - let path = PathBuf::from(&*path_sym.as_str()); + let path = PathBuf::from(path_sym.as_str()); let file = FileName::from(path); escape_dep_filename(&file.prefer_local().to_string()) }); @@ -1033,8 +1049,8 @@ let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); if need_metadata_file { - let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str(); - let out_filename = filename_for_metadata(tcx.sess, crate_name, outputs); + let crate_name = tcx.crate_name(LOCAL_CRATE); + let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/queries.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/queries.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/queries.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/queries.rs 2022-02-23 04:07:21.000000000 +0000 @@ -335,8 +335,11 @@ impl Linker { pub fn link(self) -> Result<()> { - let (codegen_results, work_products) = - self.codegen_backend.join_codegen(self.ongoing_codegen, &self.sess)?; + let (codegen_results, work_products) = self.codegen_backend.join_codegen( + self.ongoing_codegen, + &self.sess, + &self.prepare_outputs, + )?; self.sess.compile_status()?; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -593,6 +593,7 @@ tracked!(relocation_model, Some(RelocModel::Pic)); tracked!(soft_float, true); tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); + tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); } @@ -651,7 +652,6 @@ untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); - untracked!(emit_future_incompat_report, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); untracked!(hir_stats, true); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_interface/src/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,4 @@ +use libloading::Library; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; @@ -7,7 +8,6 @@ use rustc_data_structures::jobserver; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; -use rustc_metadata::dynamic_lib::DynamicLibrary; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; use rustc_parse::validate_attr; @@ -39,6 +39,9 @@ use std::thread; use tracing::info; +/// Function pointer type that constructs a new CodegenBackend. +pub type MakeBackendFn = fn() -> Box; + /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// @@ -211,28 +214,24 @@ }) } -fn load_backend_from_dylib(path: &Path) -> fn() -> Box { - let lib = DynamicLibrary::open(path).unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); +fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { + let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { + let err = format!("couldn't load codegen backend {:?}: {}", path, err); early_error(ErrorOutputType::default(), &err); }); - unsafe { - match lib.symbol("__rustc_codegen_backend") { - Ok(f) => { - mem::forget(lib); - mem::transmute::<*mut u8, _>(f) - } - Err(e) => { - let err = format!( - "couldn't load codegen backend as it \ - doesn't export the `__rustc_codegen_backend` \ - symbol: {:?}", - e - ); - early_error(ErrorOutputType::default(), &err); - } - } - } + + let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } + .unwrap_or_else(|e| { + let err = format!("couldn't load codegen backend: {}", e); + early_error(ErrorOutputType::default(), &err); + }); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + let backend_sym = unsafe { backend_sym.into_raw() }; + mem::forget(lib); + + *backend_sym } /// Get the codegen backend based on the name and specified sysroot. @@ -380,10 +379,7 @@ } } -pub fn get_codegen_sysroot( - maybe_sysroot: &Option, - backend_name: &str, -) -> fn() -> Box { +pub fn get_codegen_sysroot(maybe_sysroot: &Option, 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 // general this assertion never trips due to the once guard in `get_codegen_backend`, @@ -488,7 +484,7 @@ return; } - if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { + if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { let span = spanned.span; let lev_candidate = find_best_match_for_name( &CRATE_TYPES.iter().map(|(k, _)| *k).collect::>(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/cursor.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/cursor.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/cursor.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/cursor.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,10 +2,11 @@ /// Peekable iterator over a char sequence. /// -/// Next characters can be peeked via `nth_char` method, +/// Next characters can be peeked via `first` method, /// and position can be shifted forward via `bump` method. pub(crate) struct Cursor<'a> { initial_len: usize, + /// Iterator over chars. Slightly faster than a &str. chars: Chars<'a>, #[cfg(debug_assertions)] prev: char, @@ -37,22 +38,21 @@ } } - /// Returns nth character relative to the current cursor position. + /// Peeks the next symbol from the input stream without consuming it. /// If requested position doesn't exist, `EOF_CHAR` is returned. /// However, getting `EOF_CHAR` doesn't always mean actual end of file, /// it should be checked with `is_eof` method. - fn nth_char(&self, n: usize) -> char { - self.chars().nth(n).unwrap_or(EOF_CHAR) - } - - /// Peeks the next symbol from the input stream without consuming it. pub(crate) fn first(&self) -> char { - self.nth_char(0) + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) } /// Peeks the second symbol from the input stream without consuming it. pub(crate) fn second(&self) -> char { - self.nth_char(1) + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) } /// Checks if there is nothing more to consume. @@ -65,9 +65,9 @@ self.initial_len - self.chars.as_str().len() } - /// Returns a `Chars` iterator over the remaining characters. - fn chars(&self) -> Chars<'a> { - self.chars.clone() + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_len_consumed(&mut self) { + self.initial_len = self.chars.as_str().len(); } /// Moves to the next character. @@ -81,4 +81,13 @@ Some(c) } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lexer/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -227,14 +227,15 @@ } /// Creates an iterator that produces tokens from the input string. -pub fn tokenize(mut input: &str) -> impl Iterator + '_ { +pub fn tokenize(input: &str) -> impl Iterator + '_ { + let mut cursor = Cursor::new(input); std::iter::from_fn(move || { - if input.is_empty() { - return None; + if cursor.is_eof() { + None + } else { + cursor.reset_len_consumed(); + Some(cursor.advance_token()) } - let token = first_token(input); - input = &input[token.len..]; - Some(token) }) } @@ -832,11 +833,4 @@ self.eat_while(is_id_continue); } - - /// Eats symbols while predicate returns true or until the end of file is reached. - fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/array_into_iter.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/array_into_iter.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/array_into_iter.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/array_into_iter.rs 2022-02-23 04:07:21.000000000 +0000 @@ -52,7 +52,7 @@ if let hir::ExprKind::Call(path, [arg]) = &arg.kind { if let hir::ExprKind::Path(hir::QPath::LangItem( hir::LangItem::IntoIterIntoIter, - _, + .., )) = &path.kind { self.for_expr_span = arg.span; @@ -79,9 +79,8 @@ let receiver_ty = cx.typeck_results().expr_ty(receiver_arg); let adjustments = cx.typeck_results().expr_adjustments(receiver_arg); - let target = match adjustments.last() { - Some(Adjustment { kind: Adjust::Borrow(_), target }) => target, - _ => return, + let Some(Adjustment { kind: Adjust::Borrow(_), target }) = adjustments.last() else { + return }; let types = diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/builtin.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/builtin.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/builtin.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/builtin.rs 2022-02-23 04:07:21.000000000 +0000 @@ -609,14 +609,12 @@ // If the trait is private, add the impl items to `private_traits` so they don't get // reported for missing docs. let real_trait = trait_ref.path.res.def_id(); - if let Some(def_id) = real_trait.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) { - if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in items { - self.private_traits.insert(impl_item_ref.id.hir_id()); - } - } + let Some(def_id) = real_trait.as_local() else { return }; + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) else { return }; + if let hir::VisibilityKind::Inherited = item.vis.node { + for impl_item_ref in items { + self.private_traits.insert(impl_item_ref.id.hir_id()); } } return; @@ -829,9 +827,8 @@ _ => return, } - let debug = match cx.tcx.get_diagnostic_item(sym::Debug) { - Some(debug) => debug, - None => return, + let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { + return }; if self.impling_types.is_none() { @@ -1079,6 +1076,10 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { warn_if_doc(cx, expr.span, "expressions", &expr.attrs); } + + fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) { + warn_if_doc(cx, param.ident.span, "generic parameters", ¶m.attrs); + } } declare_lint! { @@ -1505,9 +1506,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - let (ty, type_alias_generics) = match item.kind { - hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics), - _ => return, + let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { + return }; if let hir::TyKind::OpaqueDef(..) = ty.kind { // Bounds are respected for `type X = impl Trait` @@ -2262,16 +2262,15 @@ // and should check for them here. match predicate.bounded_ty.kind { hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { - if let Res::Def(DefKind::TyParam, def_id) = path.res { - let index = ty_generics.param_def_id_to_index[&def_id]; - ( - Self::lifetimes_outliving_type(inferred_outlives, index), - &predicate.bounds, - predicate.span, - ) - } else { - continue; - } + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + ) } _ => { continue; @@ -3011,7 +3010,7 @@ this_decl_ty, CItemKind::Declaration, ) { - let orig_fi = tcx.hir().expect_foreign_item(existing_hid); + let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner()); let orig = Self::name_of_extern_decl(tcx, orig_fi); // We want to ensure that we use spans for both decls that include where the @@ -3148,7 +3147,8 @@ /// ### Example /// /// ```rust,compile_fail - /// #![feature(asm)] + /// use std::arch::asm; + /// /// fn main() { /// unsafe { /// asm!("foo: bar"); @@ -3165,10 +3165,10 @@ /// of this, GNU assembler [local labels] *must* be used instead of labels /// with a name. Using named labels might cause assembler or linker errors. /// - /// See the [unstable book] for more details. + /// See the explanation in [Rust By Example] for more details. /// /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels - /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels + /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels pub NAMED_ASM_LABELS, Deny, "named labels in inline assembly", @@ -3184,7 +3184,7 @@ } = expr { for (template_sym, template_snippet, template_span) in template_strs.iter() { - let template_str = &template_sym.as_str(); + let template_str = template_sym.as_str(); let find_label_span = |needle: &str| -> Option { if let Some(template_snippet) = template_snippet { let snippet = template_snippet.as_str(); @@ -3212,18 +3212,17 @@ for (idx, _) in statement.match_indices(':') { let possible_label = statement[start_idx..idx].trim(); let mut chars = possible_label.chars(); - if let Some(c) = chars.next() { - // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ - if (c.is_alphabetic() || matches!(c, '.' | '_')) - && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) - { - found_labels.push(possible_label); - } else { - // If we encounter a non-label, there cannot be any further labels, so stop checking - break; - } - } else { + let Some(c) = chars.next() else { // Empty string means a leading ':' in this section, which is not a label + break + }; + // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ + if (c.is_alphabetic() || matches!(c, '.' | '_')) + && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) + { + found_labels.push(possible_label); + } else { + // If we encounter a non-label, there cannot be any further labels, so stop checking break; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/context.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/context.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/context.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/context.rs 2022-02-23 04:07:21.000000000 +0000 @@ -22,9 +22,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_errors::{ - add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability, SuggestionStyle, -}; +use rustc_errors::{struct_span_err, Applicability, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -383,10 +381,10 @@ lint_name, self.lint_groups.keys().collect::>() ); - let lint_name_str = &*lint_name.as_str(); - self.lint_groups.contains_key(&lint_name_str) || { + let lint_name_str = lint_name.as_str(); + self.lint_groups.contains_key(lint_name_str) || { let warnings_name_str = crate::WARNINGS.name_lower(); - lint_name_str == &*warnings_name_str + lint_name_str == warnings_name_str } } @@ -635,16 +633,6 @@ } }, BuiltinLintDiagnostics::Normal => (), - BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { - Ok(s) if is_global => { - (format!("dyn ({})", s), Applicability::MachineApplicable) - } - Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), - Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), - }; - db.span_suggestion(span, "use `dyn`", sugg, app); - } BuiltinLintDiagnostics::AbsPathWithModule(span) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { @@ -670,27 +658,10 @@ ) => { db.span_note(span_def, "the macro is defined here"); } - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ) => { - add_elided_lifetime_in_path_suggestion( - sess.source_map(), - &mut db, - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ); - } BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect); } - BuiltinLintDiagnostics::UnusedImports(message, replaces) => { + BuiltinLintDiagnostics::UnusedImports(message, replaces, in_test_module) => { if !replaces.is_empty() { db.tool_only_multipart_suggestion( &message, @@ -698,6 +669,14 @@ Applicability::MachineApplicable, ); } + + if let Some(span) = in_test_module { + let def_span = self.sess().source_map().guess_head_span(span); + db.span_help( + span.shrink_to_lo().to(def_span), + "consider adding a `#[cfg(test)]` to the containing module", + ); + } } BuiltinLintDiagnostics::RedundantImport(spans, ident) => { for (span, is_imported) in spans { @@ -791,7 +770,7 @@ } BuiltinLintDiagnostics::NamedAsmLabel(help) => { db.help(&help); - db.note("see the asm section of the unstable book for more information"); + db.note("see the asm section of Rust By Example for more information"); } } // Rewrap `db`, and pass control to the user. @@ -1060,8 +1039,8 @@ ) -> Result { let mut path = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(path); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs 2022-02-23 04:07:21.000000000 +0000 @@ -91,16 +91,14 @@ impl<'tcx> LateLintPass<'tcx> for EnumIntrinsicsNonEnums { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { - if let hir::ExprKind::Call(ref func, ref args) = expr.kind { - if let hir::ExprKind::Path(ref qpath) = func.kind { - if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() { - if cx.tcx.is_diagnostic_item(sym::mem_discriminant, def_id) { - enforce_mem_discriminant(cx, func, expr.span, args[0].span); - } else if cx.tcx.is_diagnostic_item(sym::mem_variant_count, def_id) { - enforce_mem_variant_count(cx, func, expr.span); - } - } - } + let hir::ExprKind::Call(func, args) = &expr.kind else { return }; + let hir::ExprKind::Path(qpath) = &func.kind else { return }; + let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() else { return }; + let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return }; + match name { + sym::mem_discriminant => enforce_mem_discriminant(cx, func, expr.span, args[0].span), + sym::mem_variant_count => enforce_mem_variant_count(cx, func, expr.span), + _ => {} } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/hidden_unicode_codepoints.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/hidden_unicode_codepoints.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/hidden_unicode_codepoints.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/hidden_unicode_codepoints.rs 2022-02-23 04:07:21.000000000 +0000 @@ -127,7 +127,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if let ast::AttrKind::DocComment(_, comment) = attr.kind { - if contains_text_flow_control_chars(&comment.as_str()) { + if contains_text_flow_control_chars(comment.as_str()) { self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment"); } } @@ -138,7 +138,7 @@ let (text, span, padding) = match &expr.kind { ast::ExprKind::Lit(ast::Lit { token, kind, span }) => { let text = token.symbol; - if !contains_text_flow_control_chars(&text.as_str()) { + if !contains_text_flow_control_chars(text.as_str()) { return; } let padding = match kind { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/levels.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/levels.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/levels.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/levels.rs 2022-02-23 04:07:21.000000000 +0000 @@ -154,7 +154,7 @@ LintLevelSource::Node(_, forbid_source_span, reason) => { diag_builder.span_label(forbid_source_span, "`forbid` level set here"); if let Some(rationale) = reason { - diag_builder.note(&rationale.as_str()); + diag_builder.note(rationale.as_str()); } } LintLevelSource::CommandLine(_, _) => { @@ -227,14 +227,12 @@ let sess = self.sess; let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input"); for attr in attrs { - let level = match Level::from_symbol(attr.name_or_empty()) { - None => continue, - Some(lvl) => lvl, + let Some(level) = Level::from_symbol(attr.name_or_empty()) else { + continue }; - let mut metas = match attr.meta_item_list() { - Some(x) => x, - None => continue, + let Some(mut metas) = attr.meta_item_list() else { + continue }; if metas.is_empty() { @@ -481,9 +479,8 @@ continue; } - let (lint_attr_name, lint_attr_span) = match *src { - LintLevelSource::Node(name, span, _) => (name, span), - _ => continue, + let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else { + continue }; let lint = builtin::UNUSED_ATTRIBUTES; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -30,9 +30,8 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_order_by)] -#![feature(iter_zip)] +#![feature(let_else)] #![feature(never_type)] #![feature(nll)] #![feature(control_flow_enum)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_ascii_idents.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_ascii_idents.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_ascii_idents.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_ascii_idents.rs 2022-02-23 04:07:21.000000000 +0000 @@ -218,8 +218,7 @@ cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| { lint.build(&format!( "identifier pair considered confusable between `{}` and `{}`", - existing_symbol.as_str(), - symbol.as_str() + existing_symbol, symbol )) .span_label( *existing_span, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_fmt_panic.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_fmt_panic.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_fmt_panic.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/non_fmt_panic.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::edition::Edition; -use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol}; +use rustc_span::{hygiene, sym, symbol::kw, InnerSpan, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; declare_lint! { @@ -49,9 +49,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Call(f, [arg]) = &expr.kind { if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() { + let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id); + if Some(def_id) == cx.tcx.lang_items().begin_panic_fn() || Some(def_id) == cx.tcx.lang_items().panic_fn() - || Some(def_id) == cx.tcx.lang_items().panic_str() + || f_diagnostic_name == Some(sym::panic_str) { if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id { if matches!( @@ -61,6 +63,22 @@ check_panic(cx, f, arg); } } + } else if f_diagnostic_name == Some(sym::unreachable_display) { + if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id { + if cx.tcx.is_diagnostic_item(sym::unreachable_2015_macro, id) { + check_panic( + cx, + f, + // This is safe because we checked above that the callee is indeed + // unreachable_display + match &arg.kind { + // Get the borrowed arg not the borrow + hir::ExprKind::AddrOf(ast::BorrowKind::Ref, _, arg) => arg, + _ => bug!("call to unreachable_display without borrow"), + }, + ); + } + } } } } @@ -71,22 +89,22 @@ if let hir::ExprKind::Lit(lit) = &arg.kind { if let ast::LitKind::Str(sym, _) = lit.node { // The argument is a string literal. - check_panic_str(cx, f, arg, &sym.as_str()); + check_panic_str(cx, f, arg, sym.as_str()); return; } } // The argument is *not* a string literal. - let (span, panic, symbol_str) = panic_call(cx, f); + let (span, panic, symbol) = panic_call(cx, f); if in_external_macro(cx.sess(), span) { // Nothing that can be done about it in the current crate. return; } - // Find the span of the argument to `panic!()`, before expansion in the - // case of `panic!(some_macro!())`. + // Find the span of the argument to `panic!()` or `unreachable!`, before expansion in the + // case of `panic!(some_macro!())` or `unreachable!(some_macro!())`. // We don't use source_callsite(), because this `panic!(..)` might itself // be expanded from another macro, in which case we want to stop at that // expansion. @@ -103,7 +121,7 @@ cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| { let mut l = lint.build("panic message is not a string literal"); - l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol_str)); + l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol)); l.note("for more information, see "); if !is_arg_inside_call(arg_span, span) { // No clue where this argument is coming from. @@ -112,7 +130,7 @@ } if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) { // A case of `panic!(format!(..))`. - l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol_str).as_str()); + l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol).as_str()); if let Some((open, close, _)) = find_delimiters(cx, arg_span) { l.multipart_suggestion( "remove the `format!(..)` macro call", @@ -207,7 +225,7 @@ arg: &'tcx hir::Expr<'tcx>, fmt: &str, ) { - if !fmt.contains(&['{', '}'][..]) { + if !fmt.contains(&['{', '}']) { // No brace, no problem. return; } @@ -301,7 +319,7 @@ )) } -fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, SymbolStr) { +fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, Symbol) { let mut expn = f.span.ctxt().outer_expn_data(); let mut panic_macro = kw::Empty; @@ -309,19 +327,27 @@ // Unwrap more levels of macro expansion, as panic_2015!() // was likely expanded from panic!() and possibly from // [debug_]assert!(). - for &i in - &[sym::std_panic_macro, sym::core_panic_macro, sym::assert_macro, sym::debug_assert_macro] - { + loop { let parent = expn.call_site.ctxt().outer_expn_data(); - if parent.macro_def_id.map_or(false, |id| cx.tcx.is_diagnostic_item(i, id)) { - expn = parent; - panic_macro = i; + let Some(id) = parent.macro_def_id else { break }; + let Some(name) = cx.tcx.get_diagnostic_name(id) else { break }; + if !matches!( + name, + sym::core_panic_macro + | sym::std_panic_macro + | sym::assert_macro + | sym::debug_assert_macro + | sym::unreachable_macro + ) { + break; } + expn = parent; + panic_macro = name; } let macro_symbol = if let hygiene::ExpnKind::Macro(_, symbol) = expn.kind { symbol } else { sym::panic }; - (expn.call_site, panic_macro, macro_symbol.as_str()) + (expn.call_site, panic_macro, macro_symbol) } fn is_arg_inside_call(arg: Span, call: Span) -> bool { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/nonstandard_style.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/nonstandard_style.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/nonstandard_style.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/nonstandard_style.rs 2022-02-23 04:07:21.000000000 +0000 @@ -133,7 +133,7 @@ impl NonCamelCaseTypes { fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) { - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if !is_camel_case(name) { cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { @@ -276,7 +276,7 @@ }) } - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if !is_snake_case(name) { cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { @@ -484,7 +484,7 @@ impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if name.chars().any(|c| c.is_lowercase()) { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/noop_method_call.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/noop_method_call.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/noop_method_call.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/noop_method_call.rs 2022-02-23 04:07:21.000000000 +0000 @@ -40,9 +40,8 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // We only care about method calls. - let (call, elements) = match expr.kind { - ExprKind::MethodCall(call, _, elements, _) => (call, elements), - _ => return, + let ExprKind::MethodCall(call, _, elements, _) = &expr.kind else { + return }; // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow` // traits and ignore any other method call. @@ -70,43 +69,40 @@ } let param_env = cx.tcx.param_env(trait_id); // Resolve the trait method instance. - let i = match ty::Instance::resolve(cx.tcx, param_env, did, substs) { - Ok(Some(i)) => i, - _ => return, + let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) else { + return }; // (Re)check that it implements the noop diagnostic. - for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() { - if cx.tcx.is_diagnostic_item(*s, i.def_id()) { - let method = &call.ident.name; - let receiver = &elements[0]; - let receiver_ty = cx.typeck_results().expr_ty(receiver); - let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); - if receiver_ty != expr_ty { - // This lint will only trigger if the receiver type and resulting expression \ - // type are the same, implying that the method call is unnecessary. - return; - } - let expr_span = expr.span; - let note = format!( - "the type `{:?}` which `{}` is being called on is the same as \ - the type returned from `{}`, so the method call does not do \ - anything and can be removed", - receiver_ty, method, method, - ); - - let span = expr_span.with_lo(receiver.span.hi()); - cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| { - let method = &call.ident.name; - let message = format!( - "call to `.{}()` on a reference in this situation does nothing", - &method, - ); - lint.build(&message) - .span_label(span, "unnecessary method call") - .note(¬e) - .emit() - }); - } + let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; + if !matches!( + name, + sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref + ) { + return; + } + let method = &call.ident.name; + let receiver = &elements[0]; + let receiver_ty = cx.typeck_results().expr_ty(receiver); + let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); + if receiver_ty != expr_ty { + // This lint will only trigger if the receiver type and resulting expression \ + // type are the same, implying that the method call is unnecessary. + return; } + let expr_span = expr.span; + let note = format!( + "the type `{:?}` which `{}` is being called on is the same as \ + the type returned from `{}`, so the method call does not do \ + anything and can be removed", + receiver_ty, method, method, + ); + + let span = expr_span.with_lo(receiver.span.hi()); + cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| { + let method = &call.ident.name; + let message = + format!("call to `.{}()` on a reference in this situation does nothing", &method,); + lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit() + }); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/traits.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/traits.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/traits.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/traits.rs 2022-02-23 04:07:21.000000000 +0000 @@ -91,9 +91,8 @@ let predicates = cx.tcx.explicit_predicates_of(item.def_id); for &(predicate, span) in predicates.predicates { - let trait_predicate = match predicate.kind().skip_binder() { - Trait(trait_predicate) => trait_predicate, - _ => continue, + let Trait(trait_predicate) = predicate.kind().skip_binder() else { + continue }; if trait_predicate.constness == ty::BoundConstness::ConstIfConst { // `~const Drop` definitely have meanings so avoid linting here. @@ -106,9 +105,8 @@ continue; } cx.struct_span_lint(DROP_BOUNDS, span, |lint| { - let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { - Some(needs_drop) => needs_drop, - None => return, + let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return }; let msg = format!( "bounds on `{}` are most likely incorrect, consider instead \ @@ -123,17 +121,15 @@ } fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { - let bounds = match &ty.kind { - hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds, - _ => return, + let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { + return }; for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); if cx.tcx.lang_items().drop_trait() == def_id { cx.struct_span_lint(DYN_DROP, bound.span, |lint| { - let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { - Some(needs_drop) => needs_drop, - None => return, + let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return }; let msg = format!( "types that do not implement `Drop` can still have drop glue, consider \ diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/types.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/types.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/types.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/types.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1337,14 +1337,15 @@ let layout = match cx.layout_of(ty) { Ok(layout) => layout, Err( - ty::layout::LayoutError::Unknown(_) | ty::layout::LayoutError::SizeOverflow(_), + ty::layout::LayoutError::Unknown(_) + | ty::layout::LayoutError::SizeOverflow(_) + | ty::layout::LayoutError::NormalizationFailure(_, _), ) => return, }; - let (variants, tag) = match layout.variants { - Variants::Multiple { + let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, ref variants, .. - } => (variants, tag), - _ => return, + } = &layout.variants else { + return }; let tag_size = tag.value.size(&cx.tcx).bytes(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/unused.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/unused.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/unused.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint/src/unused.rs 2022-02-23 04:07:21.000000000 +0000 @@ -169,7 +169,9 @@ } if !(type_permits_lack_of_use || fn_warned || op_warned) { - cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| lint.build("unused result").emit()); + cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| { + lint.build(&format!("unused result of type `{}`", ty)).emit() + }); } // Returns whether an error has been emitted (and thus another does not need to be later). @@ -313,7 +315,7 @@ let mut err = lint.build(&msg); // check for #[must_use = "..."] if let Some(note) = attr.value_str() { - err.note(¬e.as_str()); + err.note(note.as_str()); } err.emit(); }); @@ -476,8 +478,11 @@ lhs_needs_parens || (followed_by_block - && match inner.kind { + && match &inner.kind { ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true, + ExprKind::Range(_lhs, Some(rhs), _limits) => { + matches!(rhs.kind, ExprKind::Block(..)) + } _ => parser::contains_exterior_struct_lit(&inner), }) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/builtin.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/builtin.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/builtin.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/builtin.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2419,8 +2419,9 @@ /// /// ### Example /// - /// ```rust,ignore (fails on system llvm) - /// #![feature(asm)] + /// ```rust,ignore (fails on non-x86_64) + /// #[cfg(target_arch="x86_64")] + /// use std::arch::asm; /// /// fn main() { /// #[cfg(target_arch="x86_64")] @@ -2430,19 +2431,7 @@ /// } /// ``` /// - /// This will produce: - /// - /// ```text - /// warning: formatting may not be suitable for sub-register argument - /// --> src/main.rs:6:19 - /// | - /// 6 | asm!("mov {0}, {0}", in(reg) 0i16); - /// | ^^^ ^^^ ---- for this argument - /// | - /// = note: `#[warn(asm_sub_register)]` on by default - /// = help: use the `x` modifier to have the register formatted as `ax` - /// = help: or use the `r` modifier to keep the default formatting of `rax` - /// ``` + /// {{produces}} /// /// ### Explanation /// @@ -2456,9 +2445,9 @@ /// fix this, add the suggested modifier to the template, or cast the /// value to the correct size. /// - /// See [register template modifiers] for more details. + /// See [register template modifiers] in the reference for more details. /// - /// [register template modifiers]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#register-template-modifiers + /// [register template modifiers]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html#template-modifiers pub ASM_SUB_REGISTER, Warn, "using only a subset of a register for inline asm inputs", @@ -2470,34 +2459,22 @@ /// /// ### Example /// - /// ```rust,ignore (fails on system llvm) - /// #![feature(asm)] + /// ```rust,ignore (fails on non-x86_64) + /// #[cfg(target_arch="x86_64")] + /// use std::arch::asm; /// /// fn main() { /// #[cfg(target_arch="x86_64")] /// unsafe { /// asm!( /// ".att_syntax", - /// "movl {0}, {0}", in(reg) 0usize + /// "movq %{0}, %{0}", in(reg) 0usize /// ); /// } /// } /// ``` /// - /// This will produce: - /// - /// ```text - /// warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - /// --> test.rs:7:14 - /// | - /// 7 | ".att_syntax", - /// | ^^^^^^^^^^^ - /// 8 | "movq {0}, {0}", out(reg) _, - /// 9 | ); - /// | - help: add option: `, options(att_syntax)` - /// | - /// = note: `#[warn(bad_asm_style)]` on by default - /// ``` + /// {{produces}} /// /// ### Explanation /// @@ -2739,7 +2716,8 @@ /// /// ```rust /// #![feature(naked_functions)] - /// #![feature(asm)] + /// + /// use std::arch::asm; /// /// #[naked] /// pub fn default_abi() -> u32 { @@ -2960,6 +2938,41 @@ "detects large moves or copies", } +declare_lint! { + /// The `deprecated_cfg_attr_crate_type_name` lint detects uses of the + /// `#![cfg_attr(..., crate_type = "...")]` and + /// `#![cfg_attr(..., crate_name = "...")]` attributes to conditionally + /// specify the crate type and name in the source code. + /// + /// ### Example + /// + /// ```rust + /// #![cfg_attr(debug_assertions, crate_type = "lib")] + /// ``` + /// + /// {{produces}} + /// + /// + /// ### Explanation + /// + /// The `#![crate_type]` and `#![crate_name]` attributes require a hack in + /// the compiler to be able to change the used crate type and crate name + /// after macros have been expanded. Neither attribute works in combination + /// with Cargo as it explicitly passes `--crate-type` and `--crate-name` on + /// the commandline. These values must match the value used in the source + /// code to prevent an error. + /// + /// To fix the warning use `--crate-type` on the commandline when running + /// rustc instead of `#![cfg_attr(..., crate_type = "...")]` and + /// `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]`. + pub DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + Warn, + "detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #91632 ", + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -3056,6 +3069,8 @@ NON_EXHAUSTIVE_OMITTED_PATTERNS, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, DEREF_INTO_DYN_SUPERTRAIT, + DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + DUPLICATE_MACRO_ATTRIBUTES, ] } @@ -3593,3 +3608,32 @@ reference: "issue #89460 ", }; } + +declare_lint! { + /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro + /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test` + /// and `test_case`. + /// + /// ### Example + /// + /// ```rust,ignore (needs --test) + /// #[test] + /// #[test] + /// fn foo() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A duplicated attribute may erroneously originate from a copy-paste and the effect of it + /// being duplicated may not be obvious or desireable. + /// + /// For instance, doubling the `#[test]` attributes registers the test to be run twice with no + /// change to its environment. + /// + /// [issue #90979]: https://github.com/rust-lang/rust/issues/90979 + pub DUPLICATE_MACRO_ATTRIBUTES, + Warn, + "duplicated attribute" +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_lint_defs/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -285,13 +285,11 @@ #[derive(PartialEq, Debug)] pub enum BuiltinLintDiagnostics { Normal, - BareTraitObject(Span, /* is_global */ bool), AbsPathWithModule(Span), ProcMacroDeriveResolutionFallback(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), - ElidedLifetimesInPaths(usize, Span, bool, Span, String), UnknownCrateTypes(Span, String, String), - UnusedImports(String, Vec<(Span, String)>), + UnusedImports(String, Vec<(Span, String)>, Option), RedundantImport(Vec<(Span, bool)>, Ident), DeprecatedMacro(Option, Span), MissingAbi(Span, Abi), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/build.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/build.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/build.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/build.rs 2022-02-23 04:07:21.000000000 +0000 @@ -276,8 +276,11 @@ "stdc++" }; - // RISC-V requires libatomic for sub-word atomic operations - if target.starts_with("riscv") { + // RISC-V GCC erroneously requires libatomic for sub-word + // atomic operations. FreeBSD uses Clang as its system + // compiler and provides no libatomic in its base system so + // does not want this. + if !target.contains("freebsd") && target.starts_with("riscv") { println!("cargo:rustc-link-lib=atomic"); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp 2022-02-23 04:07:21.000000000 +0000 @@ -10,6 +10,7 @@ struct LLVMRustCounterMappingRegion { coverage::Counter Count; + coverage::Counter FalseCount; uint32_t FileID; uint32_t ExpandedFileID; uint32_t LineStart; @@ -53,7 +54,7 @@ MappingRegions.reserve(NumMappingRegions); for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( - Region.Count, Region.FileID, Region.ExpandedFileID, + Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID, Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, Region.Kind); } @@ -108,5 +109,9 @@ } extern "C" uint32_t LLVMRustCoverageMappingVersion() { - return coverage::CovMapVersion::Version4; +#if LLVM_VERSION_GE(13, 0) + return coverage::CovMapVersion::Version6; +#else + return coverage::CovMapVersion::Version5; +#endif } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp 2022-02-23 04:07:21.000000000 +0000 @@ -17,6 +17,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" @@ -753,7 +754,8 @@ void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, - const char *ExtraPasses, size_t ExtraPassesLen) { + const char *ExtraPasses, size_t ExtraPassesLen, + const char *LLVMPlugins, size_t LLVMPluginsLen) { Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); OptimizationLevel OptLevel = fromRust(OptLevelRust); @@ -924,6 +926,20 @@ } } + if (LLVMPluginsLen) { + auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); + SmallVector Plugins; + PluginsStr.split(Plugins, ',', -1, false); + for (auto PluginPath: Plugins) { + auto Plugin = PassPlugin::Load(PluginPath.str()); + if (!Plugin) { + LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); + continue; + } + Plugin->registerPassBuilderCallbacks(PB); + } + } + #if LLVM_VERSION_GE(13, 0) ModulePassManager MPM; #else diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,6 @@ #include "LLVMWrapper.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DiagnosticHandler.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GlobalVariable.h" @@ -340,14 +341,12 @@ unsigned Index, LLVMRustAttribute RustAttr) { Function *F = unwrap(Fn); - Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr)); - AttrBuilder B(Attr); - auto PAL = F->getAttributes(); + AttributeList PAL = F->getAttributes(); AttributeList PALNew; #if LLVM_VERSION_LT(14, 0) - PALNew = PAL.removeAttributes(F->getContext(), Index, B); + PALNew = PAL.removeAttribute(F->getContext(), Index, fromRust(RustAttr)); #else - PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B); + PALNew = PAL.removeAttributeAtIndex(F->getContext(), Index, fromRust(RustAttr)); #endif F->setAttributes(PALNew); } @@ -444,11 +443,20 @@ LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, char *Constraints, size_t ConstraintsLen, LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMRustAsmDialect Dialect) { + LLVMRustAsmDialect Dialect, LLVMBool CanThrow) { +#if LLVM_VERSION_GE(13, 0) + return wrap(InlineAsm::get(unwrap(Ty), + StringRef(AsmString, AsmStringLen), + StringRef(Constraints, ConstraintsLen), + HasSideEffects, IsAlignStack, + fromRust(Dialect), CanThrow)); +#else return wrap(InlineAsm::get(unwrap(Ty), StringRef(AsmString, AsmStringLen), StringRef(Constraints, ConstraintsLen), - HasSideEffects, IsAlignStack, fromRust(Dialect))); + HasSideEffects, IsAlignStack, + fromRust(Dialect))); +#endif } extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, @@ -706,6 +714,14 @@ extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } +extern "C" bool LLVMRustIsRustLLVM() { +#ifdef LLVM_RUSTLLVM + return true; +#else + return false; +#endif +} + extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, uint32_t Value) { unwrap(M)->addModuleFlag(Module::Warning, Name, Value); @@ -961,11 +977,11 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, - int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, + uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, LLVMBasicBlockRef InsertAtEnd) { return wrap(Builder->insertDeclare( unwrap(V), unwrap(VarInfo), - Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), + Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), DebugLoc(cast(unwrap(DL))), unwrap(InsertAtEnd))); } @@ -1039,11 +1055,11 @@ return wrap(Loc); } -extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { +extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() { return dwarf::DW_OP_deref; } -extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() { +extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() { return dwarf::DW_OP_plus_uconst; } @@ -1177,10 +1193,13 @@ case DK_SampleProfile: return LLVMRustDiagnosticKind::SampleProfile; case DK_OptimizationRemark: + case DK_MachineOptimizationRemark: return LLVMRustDiagnosticKind::OptimizationRemark; case DK_OptimizationRemarkMissed: + case DK_MachineOptimizationRemarkMissed: return LLVMRustDiagnosticKind::OptimizationRemarkMissed; case DK_OptimizationRemarkAnalysis: + case DK_MachineOptimizationRemarkAnalysis: return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis; case DK_OptimizationRemarkAnalysisFPCommute: return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute; @@ -1783,3 +1802,92 @@ return LLVMRustResult::Success; } } + +// Transfers ownership of DiagnosticHandler unique_ptr to the caller. +extern "C" DiagnosticHandler * +LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) { + std::unique_ptr DH = unwrap(C)->getDiagnosticHandler(); + return DH.release(); +} + +// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic +// handling. Ownership of the handler is moved to the LLVMContext. +extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C, + DiagnosticHandler *DH) { + unwrap(C)->setDiagnosticHandler(std::unique_ptr(DH)); +} + +using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy; + +// Configures a diagnostic handler that invokes provided callback when a +// backend needs to emit a diagnostic. +// +// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise +// the RemarkPasses array specifies individual passes for which remarks will be +// enabled. +extern "C" void LLVMRustContextConfigureDiagnosticHandler( + LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, bool RemarkAllPasses, + const char * const * RemarkPasses, size_t RemarkPassesLen) { + + class RustDiagnosticHandler final : public DiagnosticHandler { + public: + RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, + bool RemarkAllPasses, + std::vector RemarkPasses) + : DiagnosticHandlerCallback(DiagnosticHandlerCallback), + DiagnosticHandlerContext(DiagnosticHandlerContext), + RemarkAllPasses(RemarkAllPasses), + RemarkPasses(RemarkPasses) {} + + virtual bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (DiagnosticHandlerCallback) { + DiagnosticHandlerCallback(DI, DiagnosticHandlerContext); + return true; + } + return false; + } + + bool isAnalysisRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isMissedOptRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isPassedOptRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isAnyRemarkEnabled() const override { + return RemarkAllPasses || !RemarkPasses.empty(); + } + + private: + bool isRemarkEnabled(StringRef PassName) const { + if (RemarkAllPasses) + return true; + + for (auto &Pass : RemarkPasses) + if (Pass == PassName) + return true; + + return false; + } + + LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr; + void *DiagnosticHandlerContext = nullptr; + + bool RemarkAllPasses = false; + std::vector RemarkPasses; + }; + + std::vector Passes; + for (size_t I = 0; I != RemarkPassesLen; ++I) + Passes.push_back(RemarkPasses[I]); + + unwrap(C)->setDiagnosticHandler(std::make_unique( + DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes)); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_log/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_log/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_log/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_log/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,16 @@ +[package] +name = "rustc_log" +version = "0.0.0" +edition = "2021" + +[dependencies] +atty = "0.2" +tracing = "0.1.28" +tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } +tracing-tree = "0.2.0" + +[dev-dependencies] +rustc_span = { path = "../rustc_span" } + +[features] +max_level_info = ['tracing/max_level_info'] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_log/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_log/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_log/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_log/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,115 @@ +//! This crate allows tools to enable rust logging without having to magically +//! match rustc's tracing crate version. +//! +//! For example if someone is working on rustc_ast and wants to write some +//! minimal code against it to run in a debugger, with access to the `debug!` +//! logs emitted by rustc_ast, that can be done by writing: +//! +//! ```toml +//! [dependencies] +//! rustc_ast = { path = "../rust/compiler/rustc_ast" } +//! rustc_log = { path = "../rust/compiler/rustc_log" } +//! rustc_span = { path = "../rust/compiler/rustc_span" } +//! ``` +//! +//! ``` +//! fn main() { +//! rustc_log::init_rustc_env_logger().unwrap(); +//! +//! let edition = rustc_span::edition::Edition::Edition2021; +//! rustc_span::create_session_globals_then(edition, || { +//! /* ... */ +//! }); +//! } +//! ``` +//! +//! Now `RUSTC_LOG=debug cargo run` will run your minimal main.rs and show +//! rustc's debug logging. In a workflow like this, one might also add +//! `std::env::set_var("RUSTC_LOG", "debug")` to the top of main so that `cargo +//! run` by itself is sufficient to get logs. +//! +//! The reason rustc_log is a tiny separate crate, as opposed to exposing the +//! same things in rustc_driver only, is to enable the above workflow. If you +//! had to depend on rustc_driver in order to turn on rustc's debug logs, that's +//! an enormously bigger dependency tree; every change you make to rustc_ast (or +//! whichever piece of the compiler you are interested in) would involve +//! rebuilding all the rest of rustc up to rustc_driver in order to run your +//! main.rs. Whereas by depending only on rustc_log and the few crates you are +//! debugging, you can make changes inside those crates and quickly run main.rs +//! to read the debug logs. + +use std::env::{self, VarError}; +use std::fmt::{self, Display}; +use std::io; +use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::layer::SubscriberExt; + +pub fn init_rustc_env_logger() -> Result<(), Error> { + init_env_logger("RUSTC_LOG") +} + +/// In contrast to `init_rustc_env_logger` this allows you to choose an env var +/// other than `RUSTC_LOG`. +pub fn init_env_logger(env: &str) -> Result<(), Error> { + let filter = match env::var(env) { + Ok(env) => EnvFilter::new(env), + _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), + }; + + let color_logs = match env::var(String::from(env) + "_COLOR") { + Ok(value) => match value.as_ref() { + "always" => true, + "never" => false, + "auto" => stderr_isatty(), + _ => return Err(Error::InvalidColorValue(value)), + }, + Err(VarError::NotPresent) => stderr_isatty(), + Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), + }; + + let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) + .with_indent_lines(true) + .with_ansi(color_logs) + .with_targets(true) + .with_indent_amount(2); + #[cfg(parallel_compiler)] + let layer = layer.with_thread_ids(true).with_thread_names(true); + + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + Ok(()) +} + +pub fn stdout_isatty() -> bool { + atty::is(atty::Stream::Stdout) +} + +pub fn stderr_isatty() -> bool { + atty::is(atty::Stream::Stderr) +} + +#[derive(Debug)] +pub enum Error { + InvalidColorValue(String), + NonUnicodeColorValue, +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidColorValue(value) => write!( + formatter, + "invalid log color value '{}': expected one of always, never, or auto", + value, + ), + Error::NonUnicodeColorValue => write!( + formatter, + "non-Unicode log color value: expected one of always, never, or auto", + ), + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/query.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/query.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/query.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/query.rs 2022-02-23 04:07:21.000000000 +0000 @@ -58,6 +58,9 @@ /// Use a separate query provider for local and extern crates SeparateProvideExtern(Ident), + + /// Always remap the ParamEnv's constness before hashing and passing to the query provider + RemapEnvConstness(Ident), } impl Parse for QueryModifier { @@ -123,6 +126,8 @@ Ok(QueryModifier::EvalAlways(modifier)) } else if modifier == "separate_provide_extern" { Ok(QueryModifier::SeparateProvideExtern(modifier)) + } else if modifier == "remap_env_constness" { + Ok(QueryModifier::RemapEnvConstness(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -222,6 +227,9 @@ /// Use a separate query provider for local and extern crates separate_provide_extern: Option, + + /// Always remap the ParamEnv's constness before hashing. + remap_env_constness: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -236,6 +244,7 @@ let mut anon = None; let mut eval_always = None; let mut separate_provide_extern = None; + let mut remap_env_constness = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -335,6 +344,12 @@ } separate_provide_extern = Some(ident); } + QueryModifier::RemapEnvConstness(ident) => { + if remap_env_constness.is_some() { + panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name); + } + remap_env_constness = Some(ident) + } } } let desc = desc.unwrap_or_else(|| { @@ -351,6 +366,7 @@ anon, eval_always, separate_provide_extern, + remap_env_constness, } } @@ -485,6 +501,10 @@ if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { attributes.push(quote! { (#separate_provide_extern) }); } + // Pass on the remap_env_constness modifier + if let Some(remap_env_constness) = &modifiers.remap_env_constness { + attributes.push(quote! { (#remap_env_constness) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/serialize.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/serialize.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/serialize.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/serialize.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,7 @@ use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, quote_spanned}; use syn::parse_quote; +use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; @@ -104,6 +105,8 @@ } fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream { + let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span()); + let decode_inner_method = if let syn::Type::Reference(_) = field.ty { quote! { ::rustc_middle::ty::codec::RefDecodable::decode } } else { @@ -111,20 +114,21 @@ }; let (decode_method, opt_field_name) = if is_struct { let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string()); - ( - proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()), - quote! { #field_name, }, - ) + (proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, }) } else { - ( - proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()), - quote! {}, - ) + (proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {}) + }; + + let __decoder = quote! { __decoder }; + // Use the span of the field for the method call, so + // that backtraces will point to the field. + let decode_call = quote_spanned! {field_span=> + ::rustc_serialize::Decoder::#decode_method( + #__decoder, #opt_field_name #decode_inner_method) }; quote! { - match ::rustc_serialize::Decoder::#decode_method( - __decoder, #opt_field_name #decode_inner_method) { + match #decode_call { ::std::result::Result::Ok(__res) => __res, ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err), } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/type_foldable.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/type_foldable.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/type_foldable.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_macros/src/type_foldable.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,10 +1,15 @@ use quote::quote; +use syn::parse_quote; pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { panic!("cannot derive on union") } + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { @@ -17,7 +22,7 @@ vi.construct(|_, index| { let bind = &bindings[index]; quote! { - ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) + ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? } }) }); @@ -25,11 +30,11 @@ s.bound_impl( quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), quote! { - fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( + fn try_super_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>( self, __folder: &mut __F - ) -> Self { - match self { #body_fold } + ) -> Result { + Ok(match self { #body_fold }) } fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,7 @@ doctest = false [dependencies] -libc = "0.2" +libloading = "0.7.1" odht = { version = "0.3.1", features = ["nightly"] } snap = "1" tracing = "0.1" @@ -27,6 +27,3 @@ rustc_expand = { path = "../rustc_expand" } rustc_span = { path = "../rustc_span" } rustc_session = { path = "../rustc_session" } - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/creader.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/creader.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/creader.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/creader.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,5 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::dynamic_lib::DynamicLibrary; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -103,30 +102,23 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(fmt, "resolved crates:")?; - // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here - // that aggregates the value (and any errors that could happen). - let mut res = Ok(()); - self.0.iter_crate_data(|cnum, data| { - res = res.and( - try { - writeln!(fmt, " name: {}", data.name())?; - writeln!(fmt, " cnum: {}", cnum)?; - writeln!(fmt, " hash: {}", data.hash())?; - writeln!(fmt, " reqd: {:?}", data.dep_kind())?; - let CrateSource { dylib, rlib, rmeta } = data.source(); - if let Some(dylib) = dylib { - writeln!(fmt, " dylib: {}", dylib.0.display())?; - } - if let Some(rlib) = rlib { - writeln!(fmt, " rlib: {}", rlib.0.display())?; - } - if let Some(rmeta) = rmeta { - writeln!(fmt, " rmeta: {}", rmeta.0.display())?; - } - }, - ); - }); - res + for (cnum, data) in self.0.iter_crate_data() { + writeln!(fmt, " name: {}", data.name())?; + writeln!(fmt, " cnum: {}", cnum)?; + writeln!(fmt, " hash: {}", data.hash())?; + writeln!(fmt, " reqd: {:?}", data.dep_kind())?; + let CrateSource { dylib, rlib, rmeta } = data.source(); + if let Some(dylib) = dylib { + writeln!(fmt, " dylib: {}", dylib.0.display())?; + } + if let Some(rlib) = rlib { + writeln!(fmt, " rlib: {}", rlib.0.display())?; + } + if let Some(rmeta) = rmeta { + writeln!(fmt, " rmeta: {}", rmeta.0.display())?; + } + } + Ok(()) } } @@ -155,12 +147,10 @@ self.metas[cnum] = Some(Lrc::new(data)); } - crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) { - for (cnum, data) in self.metas.iter_enumerated() { - if let Some(data) = data { - f(cnum, data); - } - } + crate fn iter_crate_data(&self) -> impl Iterator { + self.metas + .iter_enumerated() + .filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data))) } fn push_dependencies_in_postorder(&self, deps: &mut Vec, cnum: CrateNum) { @@ -179,7 +169,9 @@ crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec { let mut deps = Vec::new(); if cnum == LOCAL_CRATE { - self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum)); + for (cnum, _) in self.iter_crate_data() { + self.push_dependencies_in_postorder(&mut deps, cnum); + } } else { self.push_dependencies_in_postorder(&mut deps, cnum); } @@ -264,21 +256,17 @@ } fn existing_match(&self, name: Symbol, hash: Option, kind: PathKind) -> Option { - let mut ret = None; - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() != name { tracing::trace!("{} did not match {}", data.name(), name); - return; + continue; } match hash { - Some(hash) if hash == data.hash() => { - ret = Some(cnum); - return; - } + Some(hash) if hash == data.hash() => return Some(cnum), Some(hash) => { debug!("actual hash {} did not match expected {}", hash, data.hash()); - return; + continue; } None => {} } @@ -293,7 +281,7 @@ // `source` stores paths which are normalized which may be different // from the strings on the command line. let source = self.cstore.get_crate_data(cnum).cdata.source(); - if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) { + if let Some(entry) = self.sess.opts.externs.get(name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { @@ -302,10 +290,10 @@ || source.rlib.as_ref().map(|(p, _)| p) == Some(l) || source.rmeta.as_ref().map(|(p, _)| p) == Some(l) }) { - ret = Some(cnum); + return Some(cnum); } } - return; + continue; } // Alright, so we've gotten this far which means that `data` has the @@ -322,15 +310,16 @@ .expect("No sources for crate") .1; if kind.matches(prev_kind) { - ret = Some(cnum); + return Some(cnum); } else { debug!( "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}", name, kind, prev_kind ); } - }); - ret + } + + None } fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { @@ -340,17 +329,14 @@ } // Check for conflicts with any crate loaded so far - let mut res = Ok(()); - self.cstore.iter_crate_data(|_, other| { - if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id - other.hash() != root.hash() - { - // but different SVH - res = Err(CrateError::SymbolConflictsOthers(root.name())); + for (_, other) in self.cstore.iter_crate_data() { + // Same stable crate id but different SVH + if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() { + return Err(CrateError::SymbolConflictsOthers(root.name())); } - }); + } - res + Ok(()) } fn verify_no_stable_crate_id_hash_conflicts( @@ -382,7 +368,7 @@ let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); let private_dep = - self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep); + self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep); // Claim this crate number and cache it let cnum = self.cstore.alloc_new_crate_num(); @@ -512,13 +498,17 @@ name: Symbol, span: Span, dep_kind: CrateDepKind, - ) -> CrateNum { + ) -> Option { self.used_extern_options.insert(name); - self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| { - let missing_core = - self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); - err.report(&self.sess, span, missing_core) - }) + match self.maybe_resolve_crate(name, dep_kind, None) { + Ok(cnum) => Some(cnum), + Err(err) => { + let missing_core = + self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + err.report(&self.sess, span, missing_core); + None + } + } } fn maybe_resolve_crate<'b>( @@ -604,13 +594,14 @@ locator.triple == self.sess.opts.target_triple || locator.is_proc_macro; Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); + break; } - }); + } result } else { LoadResult::Loaded(library) @@ -672,25 +663,19 @@ ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); - let lib = match DynamicLibrary::open(&path) { - Ok(lib) => lib, - Err(s) => return Err(CrateError::DlOpen(s)), - }; + let lib = unsafe { libloading::Library::new(path) } + .map_err(|err| CrateError::DlOpen(err.to_string()))?; - let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); - let decls = unsafe { - let sym = match lib.symbol(&sym) { - Ok(f) => f, - Err(s) => return Err(CrateError::DlSym(s)), - }; - *(sym as *const &[ProcMacro]) - }; + let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) } + .map_err(|err| CrateError::DlSym(err.to_string()))?; // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. + let sym = unsafe { sym.into_raw() }; std::mem::forget(lib); - Ok(decls) + Ok(unsafe { **sym }) } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -714,7 +699,7 @@ let mut needs_panic_runtime = self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); if data.is_panic_runtime() { // Inject a dependency from all #![needs_panic_runtime] to this @@ -724,7 +709,7 @@ }); runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit; } - }); + } // If an explicitly linked and matching panic runtime was found, or if // we just don't need one at all, then we're done here and there's @@ -751,7 +736,7 @@ }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime @@ -791,7 +776,7 @@ ); } - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -816,11 +801,9 @@ // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. - let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator); - self.cstore.iter_crate_data(|_, data| { - needs_allocator = needs_allocator || data.needs_allocator(); - }); - if !needs_allocator { + if !self.sess.contains_name(&krate.attrs, sym::needs_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) + { return; } @@ -841,23 +824,19 @@ // global allocator. let mut global_allocator = self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); - self.cstore.iter_crate_data(|_, data| { - if !data.has_global_allocator() { - return; - } - match global_allocator { - Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} \ - conflicts with global \ - allocator in: {}", + for (_, data) in self.cstore.iter_crate_data() { + if data.has_global_allocator() { + match global_allocator { + Some(other_crate) => self.sess.err(&format!( + "the `#[global_allocator]` in {} conflicts with global allocator in: {}", other_crate, data.name() - )); + )), + None => global_allocator = Some(data.name()), } - None => global_allocator = Some(data.name()), } - }); + } + if global_allocator.is_some() { self.cstore.allocator_kind = Some(AllocatorKind::Global); return; @@ -867,19 +846,12 @@ // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. - let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator); - self.cstore.iter_crate_data(|_, data| { - if data.has_default_lib_allocator() { - has_default = true; - } - }); - - if !has_default { + if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + { self.sess.err( - "no global memory allocator found but one is \ - required; link to std or \ - add `#[global_allocator]` to a static item \ - that implements the GlobalAlloc trait", + "no global memory allocator found but one is required; link to std or add \ + `#[global_allocator]` to a static item that implements the GlobalAlloc trait", ); } self.cstore.allocator_kind = Some(AllocatorKind::Default); @@ -919,14 +891,12 @@ // crate provided for this compile, but in order for this compilation to // be successfully linked we need to inject a dependency (to order the // crates on the command line correctly). - self.cstore.iter_crate_data(|cnum, data| { - if !needs_dep(data) { - return; + for (cnum, data) in self.cstore.iter_crate_data() { + if needs_dep(data) { + info!("injecting a dep from {} to {}", cnum, krate); + data.add_dependency(krate); } - - info!("injecting a dep from {} to {}", cnum, krate); - data.add_dependency(krate); - }); + } } fn report_unused_deps(&mut self, krate: &ast::Crate) { @@ -991,7 +961,7 @@ item: &ast::Item, definitions: &Definitions, def_id: LocalDefId, - ) -> CrateNum { + ) -> Option { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!( @@ -1000,7 +970,7 @@ ); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, &orig_name.as_str(), Some(item.span)); + validate_crate_name(self.sess, orig_name.as_str(), Some(item.span)); orig_name } None => item.ident.name, @@ -1011,7 +981,7 @@ CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind); + let cnum = self.resolve_crate(name, item.span, dep_kind)?; let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( @@ -1023,14 +993,14 @@ dependency_of: LOCAL_CRATE, }, ); - cnum + Some(cnum) } _ => bug!(), } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit); + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; self.update_extern_crate( cnum, @@ -1043,7 +1013,7 @@ }, ); - cnum + Some(cnum) } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib/tests.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -use super::*; - -#[test] -fn test_errors_do_not_crash() { - use std::path::Path; - - if !cfg!(unix) { - return; - } - - // Open /dev/null as a library to get an error, and make sure - // that only causes an error, and not a crash. - let path = Path::new("/dev/null"); - match DynamicLibrary::open(&path) { - Err(_) => {} - Ok(_) => panic!("Successfully opened the empty library."), - } -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/dynamic_lib.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -//! Dynamic library facilities. -//! -//! A simple wrapper over the platform's dynamic library facilities - -use std::ffi::CString; -use std::path::Path; - -pub struct DynamicLibrary { - handle: *mut u8, -} - -impl Drop for DynamicLibrary { - fn drop(&mut self) { - unsafe { dl::close(self.handle) } - } -} - -impl DynamicLibrary { - /// Lazily open a dynamic library. - pub fn open(filename: &Path) -> Result { - let maybe_library = dl::open(filename.as_os_str()); - - // The dynamic library must not be constructed if there is - // an error opening the library so the destructor does not - // run. - match maybe_library { - Err(err) => Err(err), - Ok(handle) => Ok(DynamicLibrary { handle }), - } - } - - /// Accesses the value at the symbol of the dynamic library. - pub unsafe fn symbol(&self, symbol: &str) -> Result<*mut T, String> { - // This function should have a lifetime constraint of 'a on - // T but that feature is still unimplemented - - let raw_string = CString::new(symbol).unwrap(); - let maybe_symbol_value = dl::symbol(self.handle, raw_string.as_ptr()); - - // The value must not be constructed if there is an error so - // the destructor does not run. - match maybe_symbol_value { - Err(err) => Err(err), - Ok(symbol_value) => Ok(symbol_value as *mut T), - } - } -} - -#[cfg(test)] -mod tests; - -#[cfg(unix)] -mod dl { - use std::ffi::{CString, OsStr}; - use std::os::unix::prelude::*; - - // As of the 2017 revision of the POSIX standard (IEEE 1003.1-2017), it is - // implementation-defined whether `dlerror` is thread-safe (in which case it returns the most - // recent error in the calling thread) or not thread-safe (in which case it returns the most - // recent error in *any* thread). - // - // There's no easy way to tell what strategy is used by a given POSIX implementation, so we - // lock around all calls that can modify `dlerror` in this module lest we accidentally read an - // error from a different thread. This is bulletproof when we are the *only* code using the - // dynamic library APIs at a given point in time. However, it's still possible for us to race - // with other code (see #74469) on platforms where `dlerror` is not thread-safe. - mod error { - use std::ffi::CStr; - use std::lazy::SyncLazy; - use std::sync::{Mutex, MutexGuard}; - - pub fn lock() -> MutexGuard<'static, Guard> { - static LOCK: SyncLazy> = SyncLazy::new(|| Mutex::new(Guard)); - LOCK.lock().unwrap() - } - - #[non_exhaustive] - pub struct Guard; - - impl Guard { - pub fn get(&mut self) -> Result<(), String> { - let msg = unsafe { libc::dlerror() }; - if msg.is_null() { - Ok(()) - } else { - let msg = unsafe { CStr::from_ptr(msg as *const _) }; - Err(msg.to_string_lossy().into_owned()) - } - } - - pub fn clear(&mut self) { - let _ = unsafe { libc::dlerror() }; - } - } - } - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - let s = CString::new(filename.as_bytes()).unwrap(); - - let mut dlerror = error::lock(); - let ret = unsafe { libc::dlopen(s.as_ptr(), libc::RTLD_LAZY | libc::RTLD_LOCAL) }; - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // A null return from `dlopen` indicates that an error has definitely occurred, so if - // nothing is in `dlerror`, we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Unknown error".to_string())) - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let mut dlerror = error::lock(); - - // Unlike `dlopen`, it's possible for `dlsym` to return null without overwriting `dlerror`. - // Because of this, we clear `dlerror` before calling `dlsym` to avoid picking up a stale - // error message by accident. - dlerror.clear(); - - let ret = libc::dlsym(handle as *mut libc::c_void, symbol); - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // If `dlsym` returns null but there is nothing in `dlerror` it means one of two things: - // - We tried to load a symbol mapped to address 0. This is not technically an error but is - // unlikely to occur in practice and equally unlikely to be handled correctly by calling - // code. Therefore we treat it as an error anyway. - // - An error has occurred, but we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Tried to load symbol mapped to address 0".to_string())) - } - - pub(super) unsafe fn close(handle: *mut u8) { - libc::dlclose(handle as *mut libc::c_void); - } -} - -#[cfg(windows)] -mod dl { - use std::ffi::OsStr; - use std::io; - use std::os::windows::prelude::*; - use std::ptr; - - use winapi::shared::minwindef::HMODULE; - use winapi::um::errhandlingapi::SetThreadErrorMode; - use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryW}; - use winapi::um::winbase::SEM_FAILCRITICALERRORS; - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - // disable "dll load failed" error dialog. - let prev_error_mode = unsafe { - let new_error_mode = SEM_FAILCRITICALERRORS; - let mut prev_error_mode = 0; - let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode); - if result == 0 { - return Err(io::Error::last_os_error().to_string()); - } - prev_error_mode - }; - - let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); - let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8; - let result = ptr_result(result); - - unsafe { - SetThreadErrorMode(prev_error_mode, ptr::null_mut()); - } - - result - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8; - ptr_result(ptr) - } - - pub(super) unsafe fn close(handle: *mut u8) { - FreeLibrary(handle as HMODULE); - } - - fn ptr_result(ptr: *mut T) -> Result<*mut T, String> { - if ptr.is_null() { Err(io::Error::last_os_error().to_string()) } else { Ok(ptr) } - } -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/foreign_modules.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/foreign_modules.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/foreign_modules.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/foreign_modules.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,7 +13,7 @@ modules: Vec, } -impl ItemLikeVisitor<'tcx> for Collector { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let items = match it.kind { hir::ItemKind::ForeignMod { items, .. } => items, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![feature(once_cell)] @@ -28,7 +27,6 @@ mod rmeta; pub mod creader; -pub mod dynamic_lib; pub mod locator; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/locator.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/locator.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/locator.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/locator.rs 2022-02-23 04:07:21.000000000 +0000 @@ -220,7 +220,7 @@ use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, FatalError}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; @@ -315,7 +315,7 @@ exact_paths: if hash.is_none() { sess.opts .externs - .get(&crate_name.as_str()) + .get(crate_name.as_str()) .into_iter() .filter_map(|entry| entry.files()) .flatten() @@ -734,7 +734,7 @@ } } -fn get_metadata_section( +fn get_metadata_section<'p>( target: &Target, flavor: CrateFlavor, filename: &'p Path, @@ -814,11 +814,11 @@ span: Span, name: Symbol, ) -> PathBuf { - match find_plugin_registrar_impl(sess, metadata_loader, name) { - Ok(res) => res, + find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| { // `core` is always available if we got as far as loading plugins. - Err(err) => err.report(sess, span, false), - } + err.report(sess, span, false); + FatalError.raise() + }) } fn find_plugin_registrar_impl<'a>( @@ -931,8 +931,8 @@ } impl CrateError { - crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { - let mut err = match self { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) { + let mut diag = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, &format!("cannot load a crate with a non-ascii name `{}`", crate_name), @@ -976,7 +976,8 @@ let candidates = libraries .iter() .map(|lib| { - let crate_name = &lib.metadata.get_root().name().as_str(); + let crate_name = lib.metadata.get_root().name(); + let crate_name = crate_name.as_str(); let mut paths = lib.source.paths(); // This `unwrap()` should be okay because there has to be at least one @@ -1174,7 +1175,7 @@ } else if crate_name == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime) { - err.note(&"the compiler may have been built without the profiler runtime"); + err.note("the compiler may have been built without the profiler runtime"); } else if crate_name.as_str().starts_with("rustc_") { err.help( "maybe you need to install the missing components with: \ @@ -1210,8 +1211,6 @@ ), }; - err.emit(); - sess.abort_if_errors(); - unreachable!(); + diag.emit(); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/native_libs.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/native_libs.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/native_libs.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/native_libs.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ libs: Vec, } -impl ItemLikeVisitor<'tcx> for Collector<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let (abi, foreign_mod_items) = match it.kind { hir::ItemKind::ForeignMod { abi, items } => (abi, items), @@ -67,7 +67,7 @@ Some(name) => name, None => continue, // skip like historical compilers }; - lib.kind = match &*kind.as_str() { + lib.kind = match kind.as_str() { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "static-nobundle" => { sess.struct_span_warn( @@ -132,7 +132,7 @@ if let Some(modifiers) = item.value_str() { let span = item.name_value_literal_span().unwrap(); for modifier in modifiers.as_str().split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-'][..]) { + let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { sess.span_err( @@ -223,7 +223,7 @@ fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} } -impl Collector<'tcx> { +impl Collector<'_> { fn register_native_lib(&mut self, span: Option, lib: NativeLib) { if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) { match span { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,7 +17,7 @@ use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::source_map::{Span, Spanned}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, Symbol}; use rustc_data_structures::sync::Lrc; use smallvec::SmallVec; @@ -83,7 +83,7 @@ } } -impl IntoArgs for ty::InstanceDef<'tcx> { +impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> { fn into_args(self) -> (DefId, DefId) { (self.def_id(), self.def_id()) } @@ -133,9 +133,7 @@ generator_kind => { cdata.generator_kind(def_id.index) } opt_def_kind => { Some(cdata.def_kind(def_id.index)) } def_span => { cdata.get_span(def_id.index, &tcx.sess) } - def_ident_span => { - cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span) - } + def_ident_span => { cdata.opt_item_ident(def_id.index, &tcx.sess).map(|ident| ident.span) } lookup_stability => { cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s)) } @@ -145,9 +143,7 @@ lookup_deprecation_entry => { cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) } - item_attrs => { tcx.arena.alloc_from_iter( - cdata.get_item_attrs(def_id.index, tcx.sess) - ) } + item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } fn_arg_names => { cdata.get_fn_param_names(tcx, def_id.index) } rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } @@ -195,13 +191,10 @@ extra_filename => { cdata.root.extra_filename.clone() } - implementations_of_trait => { - cdata.get_implementations_for_trait(tcx, Some(other)) - } + traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) } + all_trait_implementations => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } - all_trait_implementations => { - cdata.get_implementations_for_trait(tcx, None) - } + implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } visibility => { cdata.get_visibility(def_id.index) } dep_kind => { @@ -239,7 +232,7 @@ expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } } -pub fn provide(providers: &mut Providers) { +pub(in crate::rmeta) fn provide(providers: &mut Providers) { // FIXME(#44234) - almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in // resolve! Does this work? Unsure! That's what the issue is about @@ -295,6 +288,10 @@ use std::collections::vec_deque::VecDeque; let mut visible_parent_map: DefIdMap = Default::default(); + // This is a secondary visible_parent_map, storing the DefId of parents that re-export + // the child as `_`. Since we prefer parents that don't do this, merge this map at the + // end, only if we're missing any keys from the former. + let mut fallback_map: DefIdMap = Default::default(); // Issue 46112: We want the map to prefer the shortest // paths when reporting the path to an item. Therefore we @@ -317,12 +314,17 @@ bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX }); } - let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if !child.vis.is_public() { + let mut add_child = |bfs_queue: &mut VecDeque<_>, export: &Export, parent: DefId| { + if !export.vis.is_public() { return; } - if let Some(child) = child.res.opt_def_id() { + if let Some(child) = export.res.opt_def_id() { + if export.ident.name == kw::Underscore { + fallback_map.insert(child, parent); + return; + } + match visible_parent_map.entry(child) { Entry::Occupied(mut entry) => { // If `child` is defined in crate `cnum`, ensure @@ -345,6 +347,12 @@ } } + // Fill in any missing entries with the (less preferable) path ending in `::_`. + // We still use this path in a diagnostic that suggests importing `::*`. + for (child, parent) in fallback_map { + visible_parent_map.entry(child).or_insert(parent); + } + visible_parent_map }, @@ -357,7 +365,7 @@ tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), + crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), ..*providers }; @@ -373,9 +381,7 @@ } pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> { - self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| { - (ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index)) - }) + self.get_crate_data(def.krate).get_ctor_def_id_and_kind(def.index) } pub fn visibility_untracked(&self, def: DefId) -> Visibility { @@ -402,16 +408,12 @@ let span = data.get_span(id.index, sess); - let attrs = data.get_item_attrs(id.index, sess).collect(); - - let ident = data.item_ident(id.index, sess); - LoadedMacro::MacroDef( ast::Item { - ident, + ident: data.item_ident(id.index, sess), id: ast::DUMMY_NODE_ID, span, - attrs, + attrs: data.get_item_attrs(id.index, sess).collect(), kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)), vis: ast::Visibility { span: span.shrink_to_lo(), @@ -424,8 +426,8 @@ ) } - pub fn associated_item_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::AssocItem { - self.get_crate_data(def.krate).get_associated_item(def.index, sess) + pub fn fn_has_self_parameter_untracked(&self, def: DefId) -> bool { + self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index) } pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { @@ -440,10 +442,8 @@ self.get_crate_data(def.krate).def_kind(def.index) } - pub fn crates_untracked(&self) -> Vec { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result + pub fn crates_untracked(&self) -> impl Iterator + '_ { + self.iter_crate_data().map(|(cnum, _)| cnum) } pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { @@ -461,7 +461,7 @@ self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec { + pub fn item_attrs_untracked(&self, def_id: DefId, sess: &Session) -> Vec { self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess).collect() } @@ -521,4 +521,8 @@ ) -> ExpnId { self.get_crate_data(cnum).expn_hash_to_expn_id(sess, index_guess, hash) } + + fn import_source_files(&self, sess: &Session, cnum: CrateNum) { + self.get_crate_data(cnum).imported_source_files(sess); + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/decoder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,6 +27,7 @@ use rustc_middle::mir::{self, Body, Promoted}; use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::cstore::{ @@ -45,7 +46,8 @@ use std::path::Path; use tracing::debug; -pub use cstore_impl::{provide, provide_extern}; +pub(super) use cstore_impl::provide; +pub use cstore_impl::provide_extern; use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; @@ -91,8 +93,7 @@ /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. - trait_impls: - FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, + trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -628,7 +629,7 @@ implement_ty_decoder!(DecodeContext<'a, 'tcx>); -impl MetadataBlob { +impl<'tcx> MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { MetadataBlob(Lrc::new(metadata_ref)) } @@ -697,7 +698,7 @@ &self.triple } - crate fn decode_crate_deps( + crate fn decode_crate_deps<'a>( &self, metadata: &'a MetadataBlob, ) -> impl ExactSizeIterator + Captures<'a> { @@ -721,25 +722,24 @@ &self.raw_proc_macros.unwrap()[pos] } - fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result { - let name = self - .def_key(item_index) - .disambiguated_data - .data - .get_opt_name() - .ok_or_else(|| format!("Missing opt name for {:?}", item_index))?; - let span = self - .root - .tables - .ident_span - .get(self, item_index) - .ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))? - .decode((self, sess)); - Ok(Ident::new(name, span)) + fn opt_item_ident(&self, item_index: DefIndex, sess: &Session) -> Option { + let name = self.def_key(item_index).disambiguated_data.data.get_opt_name()?; + let span = match self.root.tables.ident_span.get(self, item_index) { + Some(lazy_span) => lazy_span.decode((self, sess)), + None => { + // FIXME: this weird case of a name with no span is specific to `extern crate` + // items, which are supposed to be treated like `use` items and only be encoded + // to metadata as `Export`s, return `None` because that's what all the callers + // expect in this case. + assert_eq!(self.def_kind(item_index), DefKind::ExternCrate); + return None; + } + }; + Some(Ident::new(name, span)) } fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident { - self.try_item_ident(item_index, sess).unwrap() + self.opt_item_ident(item_index, sess).expect("no encoded ident for item") } fn maybe_kind(&self, item_id: DefIndex) -> Option { @@ -1099,70 +1099,29 @@ }; // Iterate over all children. - let macros_only = self.dep_kind.lock().macros_only(); - if !macros_only { - let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty); - + if let Some(children) = self.root.tables.children.get(self, id) { for child_index in children.decode((self, sess)) { - // Get the item. - let child_kind = match self.maybe_kind(child_index) { - Some(child_kind) => child_kind, - None => continue, - }; - - // Hand off the item to the callback. - match child_kind { - // FIXME(eddyb) Don't encode these in children. - EntryKind::ForeignMod => { - let child_children = self - .root - .tables - .children - .get(self, child_index) - .unwrap_or_else(Lazy::empty); - for child_index in child_children.decode((self, sess)) { - let kind = self.def_kind(child_index); - callback(Export { - res: Res::Def(kind, self.local_def_id(child_index)), - ident: self.item_ident(child_index, sess), - vis: self.get_visibility(child_index), - span: self - .root - .tables - .span - .get(self, child_index) - .unwrap() - .decode((self, sess)), - }); - } + if let Some(ident) = self.opt_item_ident(child_index, sess) { + let kind = self.def_kind(child_index); + if matches!(kind, DefKind::Macro(..)) { + // FIXME: Macros are currently encoded twice, once as items and once as + // reexports. We ignore the items here and only use the reexports. continue; } - EntryKind::Impl(_) => continue, - - _ => {} - } - - let def_key = self.def_key(child_index); - if def_key.disambiguated_data.data.get_opt_name().is_some() { - let span = self.get_span(child_index, sess); - let kind = self.def_kind(child_index); - let ident = self.item_ident(child_index, sess); - let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); + let vis = self.get_visibility(child_index); + let span = self.get_span(child_index, sess); - // FIXME: Macros are currently encoded twice, once as items and once as - // reexports. We ignore the items here and only use the reexports. - if !matches!(kind, DefKind::Macro(..)) { - callback(Export { res, ident, vis, span }); - } + callback(Export { ident, res, vis, span }); // For non-re-export structs and variants add their constructors to children. // Re-export lists automatically contain constructors when necessary. match kind { DefKind::Struct => { - if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) { - let ctor_kind = self.get_ctor_kind(child_index); + if let Some((ctor_def_id, ctor_kind)) = + self.get_ctor_def_id_and_kind(child_index) + { let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); let vis = self.get_visibility(ctor_def_id.index); @@ -1174,8 +1133,9 @@ // value namespace, they are reserved for possible future use. // It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. - let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id); - let ctor_kind = self.get_ctor_kind(child_index); + let (ctor_def_id, ctor_kind) = self + .get_ctor_def_id_and_kind(child_index) + .unwrap_or((def_id, CtorKind::Fictive)); let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); let mut vis = self.get_visibility(ctor_def_id.index); @@ -1200,11 +1160,6 @@ if let EntryKind::Mod(exports) = kind { for exp in exports.decode((self, sess)) { - match exp.res { - Res::Def(DefKind::Macro(..), _) => {} - _ if macros_only => continue, - _ => {} - } callback(exp); } } @@ -1296,6 +1251,13 @@ } } + fn get_fn_has_self_parameter(&self, id: DefIndex) -> bool { + match self.kind(id) { + EntryKind::AssocFn(data) => data.decode(self).has_self, + _ => false, + } + } + fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem { let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); @@ -1326,22 +1288,11 @@ self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self) } - fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { + fn get_ctor_def_id_and_kind(&self, node_id: DefIndex) -> Option<(DefId, CtorKind)> { match self.kind(node_id) { - EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => { - data.decode(self).ctor_kind - } - _ => CtorKind::Fictive, - } - } - - fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.kind(node_id) { - EntryKind::Struct(data, _) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) - } - EntryKind::Variant(data) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) + EntryKind::Struct(data, _) | EntryKind::Variant(data) => { + let vdata = data.decode(self); + vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind)) } _ => None, } @@ -1349,24 +1300,26 @@ fn get_item_attrs( &'a self, - node_id: DefIndex, + id: DefIndex, sess: &'a Session, ) -> impl Iterator + 'a { - // The attributes for a tuple struct/variant are attached to the definition, not the ctor; - // we assume that someone passing in a tuple struct ctor is actually wanting to - // look at the definition - let def_key = self.def_key(node_id); - let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor { - def_key.parent.unwrap() - } else { - node_id - }; - self.root .tables .attributes - .get(self, item_id) - .unwrap_or_else(Lazy::empty) + .get(self, id) + .unwrap_or_else(|| { + // Structure and variant constructors don't have any attributes encoded for them, + // but we assume that someone passing a constructor ID actually wants to look at + // the attributes on the corresponding struct or variant. + let def_key = self.def_key(id); + assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor); + let parent_id = def_key.parent.expect("no parent for a constructor"); + self.root + .tables + .attributes + .get(self, parent_id) + .expect("no encoded attributes for a structure or variant") + }) .decode((self, sess)) } @@ -1408,39 +1361,43 @@ ) } - fn get_implementations_for_trait( + fn get_traits(&'a self) -> impl Iterator + 'a { + self.root.traits.decode(self).map(|index| self.local_def_id(index)) + } + + fn get_trait_impls(&'a self) -> impl Iterator)> + 'a { + self.trait_impls.values().flat_map(move |impls| { + impls + .decode(self) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) + }) + } + + fn get_implementations_of_trait( &self, tcx: TyCtxt<'tcx>, - filter: Option, - ) -> &'tcx [(DefId, Option)] { + trait_def_id: DefId, + ) -> &'tcx [(DefId, Option)] { if self.root.is_proc_macro_crate() { // proc-macro crates export no trait impls. return &[]; } - if let Some(def_id) = filter { - // Do a reverse lookup beforehand to avoid touching the crate_num - // hash map in the loop below. - let filter = match self.reverse_translate_def_id(def_id) { - Some(def_id) => (def_id.krate.as_u32(), def_id.index), - None => return &[], - }; + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + let key = match self.reverse_translate_def_id(trait_def_id) { + Some(def_id) => (def_id.krate.as_u32(), def_id.index), + None => return &[], + }; - if let Some(impls) = self.trait_impls.get(&filter) { - tcx.arena.alloc_from_iter( - impls.decode(self).map(|(idx, simplified_self_ty)| { - (self.local_def_id(idx), simplified_self_ty) - }), - ) - } else { - &[] - } - } else { - tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| { + if let Some(impls) = self.trait_impls.get(&key) { + tcx.arena.alloc_from_iter( impls .decode(self) - .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) - })) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)), + ) + } else { + &[] } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ BorrowedFromTcx(&'tcx DefPathHashMap), } -impl DefPathHashMapRef<'tcx> { +impl DefPathHashMapRef<'_> { #[inline] pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { match *self { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/encoder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/encoder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/encoder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/encoder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -26,6 +26,8 @@ use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_session::config::CrateType; @@ -611,10 +613,15 @@ self.encode_def_path_table(); let def_path_table_bytes = self.position() - i; + // Encode the def IDs of traits, for rustdoc and diagnostics. + i = self.position(); + let traits = self.encode_traits(); + let traits_bytes = self.position() - i; + // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.encode_impls(); - let impl_bytes = self.position() - i; + let impls_bytes = self.position() - i; let tcx = self.tcx; @@ -714,7 +721,7 @@ no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), - symbol_mangling_version: tcx.sess.opts.debugging_opts.get_symbol_mangling_version(), + symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, dylib_dependency_formats, @@ -725,6 +732,7 @@ native_libraries, foreign_modules, source_map, + traits, impls, exported_symbols, interpret_alloc_index, @@ -752,7 +760,8 @@ eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes); eprintln!(" native bytes: {}", native_lib_bytes); eprintln!(" source_map bytes: {}", source_map_bytes); - eprintln!(" impl bytes: {}", impl_bytes); + eprintln!(" traits bytes: {}", traits_bytes); + eprintln!(" impls bytes: {}", impls_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); @@ -869,8 +878,9 @@ let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) && tcx.sess.opts.output_types.should_codegen(); - // Only check the presence of the `const` modifier. - let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()); + // The function has a `const` modifier or is annotated with `default_method_body_is_const`. + let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) + || tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const); let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; (is_const_fn, needs_inline || always_encode_mir) } @@ -962,7 +972,7 @@ } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_def_ids(&mut self) { if self.is_proc_macro { return; @@ -1098,9 +1108,21 @@ // Encode this here because we don't do it in encode_def_ids. record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { - record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { - item_id.def_id.local_def_index - })); + let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index); + // Foreign items are planted into their parent modules from name resolution point of view. + let tcx = self.tcx; + let foreign_item_children = md + .item_ids + .iter() + .filter_map(|item_id| match tcx.hir().item(*item_id).kind { + hir::ItemKind::ForeignMod { items, .. } => { + Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index)) + } + _ => None, + }) + .flatten(); + + record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children)); } } @@ -1152,8 +1174,7 @@ debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = tcx.hir().expect_trait_item(hir_id); + let ast_item = tcx.hir().expect_trait_item(def_id.expect_local()); let trait_item = tcx.associated_item(def_id); let container = match trait_item.defaultness { @@ -1221,8 +1242,7 @@ debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = self.tcx.hir().expect_impl_item(hir_id); + let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); let impl_item = self.tcx.associated_item(def_id); let container = match impl_item.defaultness { @@ -1306,7 +1326,7 @@ }) .collect::>(); // Sort everything to ensure a stable order for diagnotics. - keys_and_jobs.sort_by_key(|&(def_id, _, _)| def_id); + keys_and_jobs.sort_by_key(|&(def_id, _, _)| def_id.index()); for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() { debug_assert!(encode_const || encode_opt); @@ -1503,11 +1523,6 @@ record!(self.tables.kind[def_id] <- entry_kind); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <- - items - .iter() - .map(|foreign_item| foreign_item.id.def_id.local_def_index) - ), hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).variants.iter().map(|v| { assert!(v.def_id.is_local()); @@ -1751,7 +1766,7 @@ fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option)]> { empty_proc_macro!(self); let tcx = self.tcx; - let lib_features = tcx.lib_features(); + let lib_features = tcx.lib_features(()); self.lazy(lib_features.to_vec()) } @@ -1783,12 +1798,17 @@ self.lazy(&tcx.lang_items().missing) } + fn encode_traits(&mut self) -> Lazy<[DefIndex]> { + empty_proc_macro!(self); + self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index)) + } + /// Encodes an index, mapping each trait to its (local) implementations. fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { + debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); - debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; - let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; + let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() }; tcx.hir().visit_all_item_likes(&mut visitor); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); @@ -1894,7 +1914,7 @@ } // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. -impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1927,7 +1947,7 @@ } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_fields(&mut self, adt_def: &ty::AdtDef) { for (variant_index, variant) in adt_def.variants.iter_enumerated() { for (field_index, _field) in variant.fields.iter().enumerate() { @@ -2033,23 +2053,30 @@ } } -struct ImplVisitor<'tcx> { +struct ImplsVisitor<'tcx> { tcx: TyCtxt<'tcx>, - impls: FxHashMap)>>, + impls: FxHashMap)>>, } -impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { +impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { - let simplified_self_ty = - ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); - - self.impls - .entry(trait_ref.def_id) - .or_default() - .push((item.def_id.local_def_index, simplified_self_ty)); + match item.kind { + hir::ItemKind::Impl(..) => { + if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { + let simplified_self_ty = fast_reject::simplify_type( + self.tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); + + self.impls + .entry(trait_ref.def_id) + .or_default() + .push((item.def_id.local_def_index, simplified_self_ty)); + } } + _ => {} } } @@ -2121,7 +2148,7 @@ #[inline] pub fn raw_data(&self) -> &[u8] { - &self.raw_data[..] + &self.raw_data } } @@ -2198,3 +2225,34 @@ EncodedMetadata { raw_data: result } } + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + traits_in_crate: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + + #[derive(Default)] + struct TraitsVisitor { + traits: Vec, + } + impl ItemLikeVisitor<'_> for TraitsVisitor { + fn visit_item(&mut self, item: &hir::Item<'_>) { + if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind { + self.traits.push(item.def_id.to_def_id()); + } + } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} + fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} + } + + let mut visitor = TraitsVisitor::default(); + tcx.hir().visit_all_item_likes(&mut visitor); + // Bring everything into deterministic order. + visitor.traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id)); + tcx.arena.alloc_slice(&visitor.traits) + }, + + ..*providers + }; +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_metadata/src/rmeta/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,6 +16,8 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir; use rustc_middle::thir; +use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; @@ -29,8 +31,8 @@ use std::marker::PhantomData; use std::num::NonZeroUsize; +pub use decoder::provide_extern; use decoder::DecodeContext; -pub use decoder::{provide, provide_extern}; crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; use encoder::EncodeContext; pub use encoder::{encode_metadata, EncodedMetadata}; @@ -48,7 +50,7 @@ /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 5; +const METADATA_VERSION: u8 = 6; /// Metadata header which includes `METADATA_VERSION`. /// @@ -222,6 +224,7 @@ diagnostic_items: Lazy<[(Symbol, DefIndex)]>, native_libraries: Lazy<[NativeLib]>, foreign_modules: Lazy<[ForeignModule]>, + traits: Lazy<[DefIndex]>, impls: Lazy<[TraitImpls]>, interpret_alloc_index: Lazy<[u32]>, proc_macro_data: Option, @@ -259,7 +262,7 @@ #[derive(MetadataEncodable, MetadataDecodable)] crate struct TraitImpls { trait_id: (u32, DefIndex), - impls: Lazy<[(DefIndex, Option)]>, + impls: Lazy<[(DefIndex, Option)]>, } /// Define `LazyTables` and `TableBuilders` at the same time. @@ -275,7 +278,7 @@ $($name: TableBuilder<$IDX, $T>),+ } - impl TableBuilders<'tcx> { + impl<'tcx> TableBuilders<'tcx> { fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> { LazyTables { $($name: self.$name.encode(buf)),+ @@ -453,3 +456,8 @@ const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; const TAG_PARTIAL_SPAN: u8 = 2; + +pub fn provide(providers: &mut Providers) { + encoder::provide(providers); + decoder::provide(providers); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/Cargo.toml 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -29,7 +29,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.55.0" +chalk-ir = "0.75.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/arena.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/arena.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/arena.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/arena.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ [] layout: rustc_target::abi::Layout, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // AdtDef are interned and compared by address - [] adt_def: rustc_middle::ty::AdtDef, + [decode] adt_def: rustc_middle::ty::AdtDef, [] steal_thir: rustc_data_structures::steal::Steal>, [] steal_mir: rustc_data_structures::steal::Steal>, [decode] mir: rustc_middle::mir::Body<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs 2022-02-23 04:07:21.000000000 +0000 @@ -201,7 +201,7 @@ // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. // Be very careful changing this type signature! -crate fn make_compile_mono_item(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { +crate fn make_compile_mono_item<'tcx>(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) } @@ -264,7 +264,7 @@ /// DepNode. Condition (2) might not be fulfilled if a DepNode /// refers to something from the previous compilation session that /// has been removed. - fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { + fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option { if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))) } else { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/hir/map/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/hir/map/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/hir/map/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/hir/map/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -474,7 +474,8 @@ /// Panics if `LocalDefId` does not have an associated body. /// /// This should only be used for determining the context of a body, a return - /// value of `Some` does not always suggest that the owner of the body is `const`. + /// value of `Some` does not always suggest that the owner of the body is `const`, + /// just that it has to be checked as if it were. pub fn body_const_context(&self, did: LocalDefId) -> Option { let hir_id = self.local_def_id_to_hir_id(did); let ccx = match self.body_owner_kind(hir_id) { @@ -869,24 +870,24 @@ bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent)) } - pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, - _ => bug!("expected item, found {}", self.node_to_string(id)), + _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, - _ => bug!("expected impl item, found {}", self.node_to_string(id)), + _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, - _ => bug!("expected trait item, found {}", self.node_to_string(id)), + _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } @@ -897,10 +898,12 @@ } } - pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, - _ => bug!("expected foreign item, found {}", self.node_to_string(id)), + _ => { + bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id))) + } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/canonical.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/canonical.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/canonical.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/canonical.rs 2022-02-23 04:07:21.000000000 +0000 @@ -75,7 +75,7 @@ pub var_values: SmallVec<[GenericArg<'tcx>; 8]>, } -impl Default for OriginalQueryValues<'tcx> { +impl<'tcx> Default for OriginalQueryValues<'tcx> { fn default() -> Self { let mut universe_map = SmallVec::default(); universe_map.push(ty::UniverseIndex::ROOT); @@ -246,6 +246,14 @@ } } +impl<'tcx, R> Canonical<'tcx, ty::ParamEnvAnd<'tcx, R>> { + #[inline] + pub fn without_const(mut self) -> Self { + self.value = self.value.without_const(); + self + } +} + impl<'tcx, V> Canonical<'tcx, V> { /// Allows you to map the `value` of a canonical while keeping the /// same set of bound variables. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/unify_key.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/unify_key.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/unify_key.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/infer/unify_key.rs 2022-02-23 04:07:21.000000000 +0000 @@ -164,7 +164,7 @@ impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {} -pub fn replace_if_possible( +pub fn replace_if_possible<'tcx, V, L>( table: &mut UnificationTable, V, L>>, c: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -33,6 +33,7 @@ #![feature(derive_default_enum)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] +#![feature(get_mut_unchecked)] #![feature(if_let_guard)] #![feature(map_first_last)] #![feature(never_type)] @@ -43,19 +44,17 @@ #![feature(let_else)] #![feature(min_specialization)] #![feature(trusted_len)] -#![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(half_open_range_patterns)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] -#![feature(iter_zip)] -#![feature(thread_local_const_init)] #![feature(trusted_step)] #![feature(try_blocks)] #![feature(try_reserve_kind)] #![feature(nonzero_ops)] +#![feature(unwrap_infallible)] #![recursion_limit = "512"] #[macro_use] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lint.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lint.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lint.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/lint.rs 2022-02-23 04:07:21.000000000 +0000 @@ -212,7 +212,7 @@ ) { // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to // the "real" work. - fn struct_lint_level_impl( + fn struct_lint_level_impl<'s, 'd>( sess: &'s Session, lint: &'static Lint, level: Level, @@ -295,7 +295,7 @@ Level::Allow => "-A", Level::ForceWarn => "--force-warn", }; - let hyphen_case_lint_name = name.replace("_", "-"); + let hyphen_case_lint_name = name.replace('_', "-"); if lint_flag_val.as_str() == name { sess.diag_note_once( &mut err, @@ -306,7 +306,7 @@ ), ); } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-"); sess.diag_note_once( &mut err, DiagnosticMessageId::from(lint), @@ -319,7 +319,7 @@ } LintLevelSource::Node(lint_attr_name, src, reason) => { if let Some(rationale) = reason { - err.note(&rationale.as_str()); + err.note(rationale.as_str()); } sess.diag_span_note_once( &mut err, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/macros.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/macros.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/macros.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/macros.rs 2022-02-23 04:07:21.000000000 +0000 @@ -52,11 +52,11 @@ (for <$tcx:lifetime> { $($ty:ty,)+ }) => { $( impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty { - fn super_fold_with>( + fn try_super_fold_with>( self, _: &mut F - ) -> $ty { - self + ) -> ::std::result::Result<$ty, F::Error> { + Ok(self) } fn super_visit_with>( @@ -95,10 +95,10 @@ impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s $(where $($wc)*)* { - fn super_fold_with>( + fn try_super_fold_with>( self, folder: &mut V, - ) -> Self { + ) -> ::std::result::Result { EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } @@ -112,9 +112,9 @@ }; (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { - match $this { + Ok(match $this { $($output)* - } + }) }; (@FoldVariants($this:expr, $folder:expr) @@ -126,7 +126,7 @@ output( $variant ( $($variant_arg),* ) => { $variant ( - $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* + $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),* ) } $($output)* @@ -145,7 +145,7 @@ $variant { $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( $variant_arg, $folder - )),* } + )?),* } } $($output)* ) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,7 @@ .map(|(f, s)| (*f, Some(*s))) .chain(self.unstable.iter().map(|f| (*f, None))) .collect(); - all_features.sort_unstable_by_key(|f| f.0.as_str()); + all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap()); all_features } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/region.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/region.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/region.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/region.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,13 +7,12 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html use crate::ty::TyCtxt; -use rustc_hir as hir; -use rustc_hir::Node; -use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; - use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir as hir; +use rustc_hir::Node; use rustc_macros::HashStable; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_span::{Span, DUMMY_SP}; use std::fmt; @@ -210,11 +209,6 @@ /// If not empty, this body is the root of this region hierarchy. pub root_body: Option, - /// The parent of the root body owner, if the latter is an - /// an associated const or method, as impls/traits can also - /// have lifetime parameters free in this body. - pub root_parent: Option, - /// Maps from a scope ID to the enclosing scope id; /// this is usually corresponding to the lexical nesting, though /// in the case of closures the parent scope is the innermost @@ -445,7 +439,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let ScopeTree { root_body, - root_parent, ref body_expr_count, ref parent_map, ref var_map, @@ -455,8 +448,7 @@ } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - root_body.hash_stable(hcx, hasher); - root_parent.hash_stable(hcx, hasher); + root_body.hash_stable(hcx, hasher) }); body_expr_count.hash_stable(hcx, hasher); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/stability.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/stability.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/stability.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/middle/stability.rs 2022-02-23 04:07:21.000000000 +0000 @@ -131,8 +131,7 @@ /// deprecated (i.e., whether X is not greater than the current rustc version). pub fn deprecation_in_effect(depr: &Deprecation) -> bool { let is_since_rustc_version = depr.is_since_rustc_version; - let since = depr.since.map(Symbol::as_str); - let since = since.as_deref(); + let since = depr.since.as_ref().map(Symbol::as_str); fn parse_version(ver: &str) -> Vec { // We ignore non-integer components of the version (e.g., "nightly"). @@ -197,7 +196,7 @@ let message = if is_in_effect { format!("use of deprecated {} `{}`", kind, path) } else { - let since = since.map(Symbol::as_str); + let since = since.as_ref().map(Symbol::as_str); if since.as_deref() == Some("TBD") { format!("use of {} `{}` that will be deprecated in a future Rust version", kind, path) @@ -229,7 +228,7 @@ ) } -pub fn early_report_deprecation( +pub fn early_report_deprecation<'a>( lint_buffer: &'a mut LintBuffer, message: &str, suggestion: Option, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/coverage.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/coverage.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/coverage.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/coverage.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,9 +21,9 @@ impl ExpressionOperandId { /// An expression operand for a "zero counter", as described in the following references: /// - /// * - /// * - /// * + /// * + /// * + /// * /// /// This operand can be used to count two or more separate code regions with a single counter, /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/generic_graphviz.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/generic_graphviz.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/generic_graphviz.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/generic_graphviz.rs 2022-02-23 04:07:21.000000000 +0000 @@ -126,7 +126,7 @@ write!( w, r#"{}"#, - dot::escape_html(§ion).replace("\n", "
") + dot::escape_html(§ion).replace('\n', "
") )?; } @@ -147,7 +147,7 @@ let src = self.node(source); let trg = self.node(target); let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) { - dot::escape_html(edge_label).replace("\n", r#"
"#) + dot::escape_html(edge_label).replace('\n', r#"
"#) } else { "".to_owned() }; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/error.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/error.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/error.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/error.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,7 +8,7 @@ use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::def_id::DefId; -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::{call, Align, Size}; use std::{any::Any, backtrace::Backtrace, fmt}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] @@ -63,7 +63,7 @@ } } -impl InterpErrorInfo<'tcx> { +impl<'tcx> InterpErrorInfo<'tcx> { pub fn print_backtrace(&self) { if let Some(backtrace) = self.0.backtrace.as_ref() { print_backtrace(backtrace); @@ -141,6 +141,10 @@ AlreadyReported(ErrorReported), /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), + /// An error occurred during FnAbi computation: the passed --target lacks FFI support + /// (which unfortunately typeck does not reject). + /// Not using `FnAbiError` as that contains a nested `LayoutError`. + FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError), /// An invalid transmute happened. TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), /// SizeOf of unsized type was requested. @@ -157,6 +161,7 @@ write!(f, "encountered constants with type errors, stopping evaluation") } Layout(ref err) => write!(f, "{}", err), + FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err), TransmuteSizeDiff(from_ty, to_ty) => write!( f, "transmuting `{}` to `{}` is not possible, because these types do not have the same size", @@ -492,9 +497,6 @@ } } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(InterpError<'_>, 64); - pub enum InterpError<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo<'tcx>), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -145,7 +145,7 @@ pub promoted: Option, } -impl GlobalId<'tcx> { +impl<'tcx> GlobalId<'tcx> { pub fn display(self, tcx: TyCtxt<'tcx>) -> String { let instance_name = with_no_trimmed_paths(|| tcx.def_path_str(self.instance.def.def_id())); if let Some(promoted) = self.promoted { @@ -273,7 +273,7 @@ impl<'s> AllocDecodingSession<'s> { /// Decodes an `AllocId` in a thread-safe way. - pub fn decode_alloc_id(&self, decoder: &mut D) -> Result + pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> Result where D: TyDecoder<'tcx>, { @@ -390,7 +390,7 @@ Memory(&'tcx Allocation), } -impl GlobalAlloc<'tcx> { +impl<'tcx> GlobalAlloc<'tcx> { /// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory` #[track_caller] #[inline] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/queries.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/queries.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/queries.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/interpret/queries.rs 2022-02-23 04:07:21.000000000 +0000 @@ -64,6 +64,7 @@ cid: GlobalId<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { + let param_env = param_env.with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(param_env.and(cid)); @@ -92,6 +93,7 @@ gid: GlobalId<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result<&'tcx mir::Allocation, ErrorHandled> { + let param_env = param_env.with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,15 +7,17 @@ use crate::mir::visit::MirVisitable; use crate::ty::adjustment::PointerCast; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; + use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; use rustc_hir::{self as hir, HirId}; +use rustc_session::Session; use rustc_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; @@ -29,6 +31,9 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; + +use either::Either; + use std::borrow::Cow; use std::convert::TryInto; use std::fmt::{self, Debug, Display, Formatter, Write}; @@ -99,7 +104,21 @@ } } + /// Returns `true` if this pass is enabled with the current combination of compiler flags. + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); + + /// If this pass causes the MIR to enter a new phase, return that phase. + fn phase_change(&self) -> Option { + None + } + + fn is_mir_dump_enabled(&self) -> bool { + true + } } /// The various "big phases" that MIR goes through. @@ -488,6 +507,16 @@ Location { block: bb, statement_index: self[bb].statements.len() } } + pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> { + let Location { block, statement_index } = location; + let block_data = &self.basic_blocks[block]; + block_data + .statements + .get(statement_index) + .map(Either::Left) + .unwrap_or_else(|| Either::Right(block_data.terminator())) + } + #[inline] pub fn predecessors(&self) -> &Predecessors { self.predecessor_cache.compute(&self.basic_blocks) @@ -1504,6 +1533,7 @@ } /// Changes a statement to a nop and returns the original statement. + #[must_use = "If you don't need the statement, use `make_nop` instead"] pub fn replace_nop(&mut self) -> Self { Statement { source_info: self.source_info, @@ -1803,6 +1833,16 @@ | Self::Downcast(_, _) => false, } } + + /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`. + pub fn is_downcast_to(&self, v: VariantIdx) -> bool { + matches!(*self, Self::Downcast(_, x) if x == v) + } + + /// Returns `true` if this is a `Field` projection with the given index. + pub fn is_field_to(&self, f: Field) -> bool { + matches!(*self, Self::Field(x, _) if x == f) + } } /// Alias for projections as they appear in places, where the base is a place @@ -1993,7 +2033,7 @@ /// Finds the original HirId this MIR item came from. /// This is necessary after MIR optimizations, as otherwise we get a HirId /// from the function that was inlined instead of the function call site. - pub fn lint_root( + pub fn lint_root<'tcx>( self, source_scopes: &IndexVec>, ) -> Option { @@ -2228,7 +2268,7 @@ /// active field number and is present only for union expressions /// -- e.g., for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option, Option), + Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option, Option), Closure(DefId, SubstsRef<'tcx>), Generator(DefId, SubstsRef<'tcx>, hir::Movability), @@ -2296,8 +2336,6 @@ SizeOf, /// Returns the minimum alignment of a type AlignOf, - /// Creates a new uninitialized box for a value of that type - Box, } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -2387,28 +2425,26 @@ } } - AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { - let variant_def = &adt_def.variants[variant]; - - let name = ty::tls::with(|tcx| { + AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => { + ty::tls::with(|tcx| { let mut name = String::new(); + let variant_def = &tcx.adt_def(adt_did).variants[variant]; let substs = tcx.lift(substs).expect("could not lift for printing"); FmtPrinter::new(tcx, &mut name, Namespace::ValueNS) .print_def_path(variant_def.def_id, substs)?; - Ok(name) - })?; - match variant_def.ctor_kind { - CtorKind::Const => fmt.write_str(&name), - CtorKind::Fn => fmt_tuple(fmt, &name), - CtorKind::Fictive => { - let mut struct_fmt = fmt.debug_struct(&name); - for (field, place) in iter::zip(&variant_def.fields, places) { - struct_fmt.field(&field.ident.as_str(), place); + match variant_def.ctor_kind { + CtorKind::Const => fmt.write_str(&name), + CtorKind::Fn => fmt_tuple(fmt, &name), + CtorKind::Fictive => { + let mut struct_fmt = fmt.debug_struct(&name); + for (field, place) in iter::zip(&variant_def.fields, places) { + struct_fmt.field(field.ident.as_str(), place); + } + struct_fmt.finish() } - struct_fmt.finish() } - } + }) } AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { @@ -2433,7 +2469,7 @@ if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); - struct_fmt.field(&var_name.as_str(), place); + struct_fmt.field(var_name.as_str(), place); } } @@ -2453,7 +2489,7 @@ if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); - struct_fmt.field(&var_name.as_str(), place); + struct_fmt.field(var_name.as_str(), place); } } @@ -2503,7 +2539,7 @@ Val(interpret::ConstValue<'tcx>, Ty<'tcx>), } -impl Constant<'tcx> { +impl<'tcx> Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { match self.literal.const_for_ty()?.val.try_to_scalar() { Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { @@ -2522,14 +2558,14 @@ } } -impl From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { +impl<'tcx> From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { #[inline] fn from(ct: &'tcx ty::Const<'tcx>) -> Self { Self::Ty(ct) } } -impl ConstantKind<'tcx> { +impl<'tcx> ConstantKind<'tcx> { /// Returns `None` if the constant is not trivially safe for use in the type system. pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> { match self { @@ -2760,11 +2796,14 @@ TrivialTypeFoldableAndLiftImpls! { ProjectionKind, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { - fn super_fold_with>(self, folder: &mut F) -> Self { - UserTypeProjection { - base: self.base.fold_with(folder), - projs: self.projs.fold_with(folder), - } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(UserTypeProjection { + base: self.base.try_fold_with(folder)?, + projs: self.projs.try_fold_with(folder)?, + }) } fn super_visit_with>( @@ -2808,7 +2847,7 @@ } } -fn pretty_print_const( +fn pretty_print_const<'tcx>( c: &ty::Const<'tcx>, fmt: &mut Formatter<'_>, print_types: bool, @@ -2823,7 +2862,7 @@ }) } -fn pretty_print_const_value( +fn pretty_print_const_value<'tcx>( val: interpret::ConstValue<'tcx>, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, @@ -2870,12 +2909,12 @@ type Iter = iter::Cloned>; } -impl graph::GraphPredecessors<'graph> for Body<'tcx> { +impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> { type Item = BasicBlock; type Iter = std::iter::Copied>; } -impl graph::WithPredecessors for Body<'tcx> { +impl<'tcx> graph::WithPredecessors for Body<'tcx> { #[inline] fn predecessors(&self, node: Self::Node) -> >::Iter { self.predecessors()[node].iter().copied() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mono.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mono.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mono.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/mono.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_hir::{HirId, ItemId}; +use rustc_hir::ItemId; use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; @@ -338,7 +338,7 @@ } pub fn work_product_id(&self) -> WorkProductId { - WorkProductId::from_cgu_name(&self.name().as_str()) + WorkProductId::from_cgu_name(self.name().as_str()) } pub fn work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct { @@ -355,7 +355,7 @@ // The codegen tests rely on items being process in the same order as // they appear in the file, so for local items, we sort by node_id first #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); + pub struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { ItemSortKey( @@ -366,10 +366,7 @@ // instances into account. The others don't matter for // the codegen tests and can even make item order // unstable. - InstanceDef::Item(def) => def - .did - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)), + InstanceDef::Item(def) => Some(def.did.index.as_usize()), InstanceDef::VtableShim(..) | InstanceDef::ReifyShim(..) | InstanceDef::Intrinsic(..) @@ -380,10 +377,10 @@ | InstanceDef::CloneShim(..) => None, } } - MonoItem::Static(def_id) => { - def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + MonoItem::Static(def_id) => Some(def_id.index.as_usize()), + MonoItem::GlobalAsm(item_id) => { + Some(item_id.def_id.to_def_id().index.as_usize()) } - MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()), }, item.symbol_name(tcx), ) @@ -431,7 +428,7 @@ cache: FxHashMap, } -impl CodegenUnitNameBuilder<'tcx> { +impl<'tcx> CodegenUnitNameBuilder<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { CodegenUnitNameBuilder { tcx, cache: Default::default() } } @@ -470,7 +467,7 @@ if self.tcx.sess.opts.debugging_opts.human_readable_cgu_names { cgu_name } else { - Symbol::intern(&CodegenUnit::mangle_name(&cgu_name.as_str())) + Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str())) } } @@ -530,6 +527,6 @@ write!(cgu_name, ".{}", special_suffix).unwrap(); } - Symbol::intern(&cgu_name[..]) + Symbol::intern(&cgu_name) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/pretty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/pretty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/pretty.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/pretty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -167,8 +167,8 @@ /// Returns the file basename portion (without extension) of a filename path /// where we should dump a MIR representation output files. -fn dump_file_basename( - tcx: TyCtxt<'_>, +fn dump_file_basename<'tcx>( + tcx: TyCtxt<'tcx>, pass_num: Option<&dyn Display>, pass_name: &str, disambiguator: &dyn Display, @@ -251,8 +251,8 @@ /// bit of MIR-related data. Used by `mir-dump`, but also by other /// bits of code (e.g., NLL inference) that dump graphviz data or /// other things, and hence takes the extension as an argument. -pub fn create_dump_file( - tcx: TyCtxt<'_>, +pub fn create_dump_file<'tcx>( + tcx: TyCtxt<'tcx>, extension: &str, pass_num: Option<&dyn Display>, pass_name: &str, @@ -419,7 +419,7 @@ comments: Vec, } -impl ExtraComments<'tcx> { +impl<'tcx> ExtraComments<'tcx> { fn push(&mut self, lines: &str) { for line in lines.split('\n') { self.comments.push(line.to_string()); @@ -427,7 +427,7 @@ } } -fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool { +fn use_verbose<'tcx>(ty: &&TyS<'tcx>, fn_def: bool) -> bool { match ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type @@ -439,7 +439,7 @@ } } -impl Visitor<'tcx> for ExtraComments<'tcx> { +impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); let Constant { span, user_ty, literal } = constant; @@ -762,7 +762,7 @@ /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints relocations adequately. -pub fn display_allocation( +pub fn display_allocation<'a, 'tcx, Tag, Extra>( tcx: TyCtxt<'tcx>, alloc: &'a Allocation, ) -> RenderAllocation<'a, 'tcx, Tag, Extra> { @@ -775,7 +775,9 @@ alloc: &'a Allocation, } -impl std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> { +impl<'a, 'tcx, Tag: Provenance, Extra> std::fmt::Display + for RenderAllocation<'a, 'tcx, Tag, Extra> +{ fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?; @@ -818,7 +820,7 @@ /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes( +fn write_allocation_bytes<'tcx, Tag: Provenance, Extra>( tcx: TyCtxt<'tcx>, alloc: &Allocation, w: &mut dyn std::fmt::Write, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/spanview.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/spanview.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/spanview.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/spanview.rs 2022-02-23 04:07:21.000000000 +0000 @@ -681,13 +681,13 @@ } fn escape_html(s: &str) -> String { - s.replace("&", "&").replace("<", "<").replace(">", ">") + s.replace('&', "&").replace('<', "<").replace('>', ">") } fn escape_attr(s: &str) -> String { - s.replace("&", "&") - .replace("\"", """) - .replace("'", "'") - .replace("<", "<") - .replace(">", ">") + s.replace('&', "&") + .replace('\"', """) + .replace('\'', "'") + .replace('<', "<") + .replace('>', ">") } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/tcx.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/tcx.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/tcx.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/tcx.rs 2022-02-23 04:07:21.000000000 +0000 @@ -195,12 +195,11 @@ } Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), - Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))), - AggregateKind::Adt(def, _, substs, _, _) => tcx.type_of(def.did).subst(tcx, substs), + AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs), AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), AggregateKind::Generator(did, substs, movability) => { tcx.mk_generator(did, substs, movability) @@ -215,9 +214,7 @@ /// whether its only shallowly initialized (`Rvalue::Box`). pub fn initialization_state(&self) -> RvalueInitializationState { match *self { - Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => { - RvalueInitializationState::Shallow - } + Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow, _ => RvalueInitializationState::Deep, } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/terminator.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/terminator.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/terminator.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/terminator.rs 2022-02-23 04:07:21.000000000 +0000 @@ -78,6 +78,13 @@ pub fn all_targets_mut(&mut self) -> &mut [BasicBlock] { &mut self.targets } + + /// Finds the `BasicBlock` to which this `SwitchInt` will branch given the + /// specific value. This cannot fail, as it'll return the `otherwise` + /// branch if there's not a specific match for the value. + pub fn target_for_value(&self, value: u128) -> BasicBlock { + self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) + } } pub struct SwitchTargetsIter<'a> { @@ -260,6 +267,10 @@ /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option, + + /// Cleanup to be done if the inline assembly unwinds. This is present + /// if and only if InlineAsmOptions::MAY_UNWIND is set. + cleanup: Option, }, } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] @@ -309,7 +320,7 @@ | Return | Unreachable | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), + | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]), Goto { target: ref t } | Call { destination: None, cleanup: Some(ref t), .. } | Call { destination: Some((_, ref t)), cleanup: None, .. } @@ -318,16 +329,20 @@ | Drop { target: ref t, unwind: None, .. } | Assert { target: ref t, cleanup: None, .. } | FalseUnwind { real_target: ref t, unwind: None } - | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), + | InlineAsm { destination: Some(ref t), cleanup: None, .. } + | InlineAsm { destination: None, cleanup: Some(ref t), .. } => { + Some(t).into_iter().chain(&[]) + } Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } | Yield { resume: ref t, drop: Some(ref u), .. } | DropAndReplace { target: ref t, unwind: Some(ref u), .. } | Drop { target: ref t, unwind: Some(ref u), .. } | Assert { target: ref t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { + | FalseUnwind { real_target: ref t, unwind: Some(ref u) } + | InlineAsm { destination: Some(ref t), cleanup: Some(ref u), .. } => { Some(t).into_iter().chain(slice::from_ref(u)) } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets[..]), + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets), FalseEdge { ref real_target, ref imaginary_target } => { Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) } @@ -343,7 +358,7 @@ | Return | Unreachable | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), + | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []), Goto { target: ref mut t } | Call { destination: None, cleanup: Some(ref mut t), .. } | Call { destination: Some((_, ref mut t)), cleanup: None, .. } @@ -352,16 +367,20 @@ | Drop { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } - | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), + | InlineAsm { destination: Some(ref mut t), cleanup: None, .. } + | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => { + Some(t).into_iter().chain(&mut []) + } Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { + | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } + | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => { Some(t).into_iter().chain(slice::from_mut(u)) } - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets[..]), + SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets), FalseEdge { ref mut real_target, ref mut imaginary_target } => { Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) } @@ -378,13 +397,13 @@ | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, + | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } | TerminatorKind::DropAndReplace { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } - | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), + | TerminatorKind::FalseUnwind { ref unwind, .. } + | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), } } @@ -398,13 +417,13 @@ | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, + | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } | TerminatorKind::DropAndReplace { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } - | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), + | TerminatorKind::FalseUnwind { ref mut unwind, .. } + | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), } } @@ -583,8 +602,12 @@ FalseEdge { .. } => vec!["real".into(), "imaginary".into()], FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], FalseUnwind { unwind: None, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), .. } => vec!["".into()], - InlineAsm { destination: None, .. } => vec![], + InlineAsm { destination: Some(_), cleanup: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()], + InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], + InlineAsm { destination: None, cleanup: None, .. } => vec![], } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/traversal.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/traversal.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/traversal.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/traversal.rs 2022-02-23 04:07:21.000000000 +0000 @@ -300,7 +300,7 @@ } /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. -pub fn reachable_as_bitset(body: &Body<'tcx>) -> BitSet { +pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet { let mut iter = preorder(body); (&mut iter).for_each(drop); iter.visited diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/type_foldable.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/type_foldable.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/type_foldable.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/type_foldable.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,37 +16,42 @@ } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::TerminatorKind::*; let kind = match self.kind { Goto { target } => Goto { target }, SwitchInt { discr, switch_ty, targets } => SwitchInt { - discr: discr.fold_with(folder), - switch_ty: switch_ty.fold_with(folder), + discr: discr.try_fold_with(folder)?, + switch_ty: switch_ty.try_fold_with(folder)?, targets, }, Drop { place, target, unwind } => { - Drop { place: place.fold_with(folder), target, unwind } + Drop { place: place.try_fold_with(folder)?, target, unwind } } DropAndReplace { place, value, target, unwind } => DropAndReplace { - place: place.fold_with(folder), - value: value.fold_with(folder), + place: place.try_fold_with(folder)?, + value: value.try_fold_with(folder)?, target, unwind, }, Yield { value, resume, resume_arg, drop } => Yield { - value: value.fold_with(folder), + value: value.try_fold_with(folder)?, resume, - resume_arg: resume_arg.fold_with(folder), + resume_arg: resume_arg.try_fold_with(folder)?, drop, }, Call { func, args, destination, cleanup, from_hir_call, fn_span } => { - let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest)); + let dest = destination + .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest)))) + .transpose()?; Call { - func: func.fold_with(folder), - args: args.fold_with(folder), + func: func.try_fold_with(folder)?, + args: args.try_fold_with(folder)?, destination: dest, cleanup, from_hir_call, @@ -56,16 +61,19 @@ Assert { cond, expected, msg, target, cleanup } => { use AssertKind::*; let msg = match msg { - BoundsCheck { len, index } => { - BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } + BoundsCheck { len, index } => BoundsCheck { + len: len.try_fold_with(folder)?, + index: index.try_fold_with(folder)?, + }, + Overflow(op, l, r) => { + Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?) } - Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)), - OverflowNeg(op) => OverflowNeg(op.fold_with(folder)), - DivisionByZero(op) => DivisionByZero(op.fold_with(folder)), - RemainderByZero(op) => RemainderByZero(op.fold_with(folder)), + OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?), + DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?), + RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?), ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg, }; - Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } + Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup } } GeneratorDrop => GeneratorDrop, Resume => Resume, @@ -76,15 +84,18 @@ FalseEdge { real_target, imaginary_target } } FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, - InlineAsm { template, operands, options, line_spans, destination } => InlineAsm { - template, - operands: operands.fold_with(folder), - options, - line_spans, - destination, - }, + InlineAsm { template, operands, options, line_spans, destination, cleanup } => { + InlineAsm { + template, + operands: operands.try_fold_with(folder)?, + options, + line_spans, + destination, + cleanup, + } + } }; - Terminator { source_info: self.source_info, kind } + Ok(Terminator { source_info: self.source_info, kind }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -140,8 +151,8 @@ } impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { @@ -150,8 +161,14 @@ } impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Place { + local: self.local.try_fold_with(folder)?, + projection: self.projection.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -161,7 +178,10 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v)) } @@ -171,47 +191,57 @@ } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::Rvalue::*; - match self { - Use(op) => Use(op.fold_with(folder)), - Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)), - ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)), - Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)), - AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)), - Len(place) => Len(place.fold_with(folder)), - Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + Ok(match self { + Use(op) => Use(op.try_fold_with(folder)?), + Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?), + ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?), + Ref(region, bk, place) => { + Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?) + } + AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?), + Len(place) => Len(place.try_fold_with(folder)?), + Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?), BinaryOp(op, box (rhs, lhs)) => { - BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) - } - CheckedBinaryOp(op, box (rhs, lhs)) => { - CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) + BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?))) } - UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp( + op, + Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)), + ), + UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?), + Discriminant(place) => Discriminant(place.try_fold_with(folder)?), + NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?), Aggregate(kind, fields) => { - let kind = kind.map_id(|kind| match kind { - AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), - AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( - def, - v, - substs.fold_with(folder), - user_ty.fold_with(folder), - n, - ), - AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) - } - AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) - } - }); - Aggregate(kind, fields.fold_with(folder)) + let kind = kind.try_map_id(|kind| { + Ok(match kind { + AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?), + AggregateKind::Tuple => AggregateKind::Tuple, + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.try_fold_with(folder)?, + user_ty.try_fold_with(folder)?, + n, + ), + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.try_fold_with(folder)?) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity) + } + }) + })?; + Aggregate(kind, fields.try_fold_with(folder)?) } - ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)), - } + ShallowInitBox(op, ty) => { + ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -265,12 +295,15 @@ } impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - match self { - Operand::Copy(place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(c) => Operand::Constant(c.fold_with(folder)), - } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(match self { + Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?), + Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?), + Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?), + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -282,19 +315,22 @@ } impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::ProjectionElem::*; - match self { + Ok(match self { Deref => Deref, - Field(f, ty) => Field(f, ty.fold_with(folder)), - Index(v) => Index(v.fold_with(folder)), + Field(f, ty) => Field(f, ty.try_fold_with(folder)?), + Index(v) => Index(v.try_fold_with(folder)?), Downcast(symbol, variantidx) => Downcast(symbol, variantidx), ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } } Subslice { from, to, from_end } => Subslice { from, to, from_end }, - } + }) } fn super_visit_with>( @@ -312,8 +348,8 @@ } impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -321,8 +357,8 @@ } impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -330,8 +366,8 @@ } impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -339,12 +375,15 @@ } impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Constant { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Constant { span: self.span, - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } + user_ty: self.user_ty.try_fold_with(folder)?, + literal: self.literal.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.literal.visit_with(visitor)?; @@ -354,14 +393,17 @@ impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { #[inline(always)] - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_mir_const(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_mir_const(self) } - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { match self { - ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), - ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)), + ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)), + ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)), } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/visit.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/visit.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/visit.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/mir/visit.rs 2022-02-23 04:07:21.000000000 +0000 @@ -412,7 +412,7 @@ for output in & $($mutability)? asm.outputs[..] { self.visit_place( output, - PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), + PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput), location ); } @@ -581,6 +581,7 @@ options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match op { @@ -590,7 +591,7 @@ InlineAsmOperand::Out { place: Some(place), .. } => { self.visit_place( place, - PlaceContext::MutatingUse(MutatingUseContext::Store), + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), location, ); } @@ -599,7 +600,7 @@ if let Some(out_place) = out_place { self.visit_place( out_place, - PlaceContext::MutatingUse(MutatingUseContext::Store), + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), location, ); } @@ -964,7 +965,7 @@ } } - fn process_projection( + fn process_projection<'a>( &mut self, projection: &'a [PlaceElem<'tcx>], location: Location, @@ -1004,8 +1005,12 @@ if new_local == local { None } else { Some(PlaceElem::Index(new_local)) } } + PlaceElem::Field(field, ty) => { + let mut new_ty = ty; + self.visit_ty(&mut new_ty, TyContext::Location(location)); + if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } + } PlaceElem::Deref - | PlaceElem::Field(..) | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } | PlaceElem::Downcast(..) => None, @@ -1174,8 +1179,10 @@ /// Appears as LHS of an assignment. Store, /// Can often be treated as a `Store`, but needs to be separate because - /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence + /// ASM is allowed to read outputs as well, so a `Store`-`LlvmAsmOutput` sequence /// cannot be simplified the way a `Store`-`Store` can be. + LlvmAsmOutput, + /// Output operand of an inline assembly block. AsmOutput, /// Destination of a call. Call, @@ -1264,6 +1271,7 @@ PlaceContext::MutatingUse( MutatingUseContext::Store | MutatingUseContext::Call + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::AsmOutput, ) ) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/query/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/query/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/query/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/query/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -522,6 +522,7 @@ } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } separate_provide_extern } query adt_destructor(key: DefId) -> Option { @@ -771,11 +772,24 @@ desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } load_cached(tcx, id) { - let typeck_results: Option> = tcx - .on_disk_cache().as_ref() - .and_then(|c| c.try_load_query_result(*tcx, id)); + #[cfg(bootstrap)] + { + match match tcx.on_disk_cache().as_ref() { + Some(c) => c.try_load_query_result(*tcx, id), + None => None, + } { + Some(x) => Some(&*tcx.arena.alloc(x)), + None => None, + } + } + #[cfg(not(bootstrap))] + { + let typeck_results: Option> = tcx + .on_disk_cache().as_ref() + .and_then(|c| c.try_load_query_result(*tcx, id)); - typeck_results.map(|x| &*tcx.arena.alloc(x)) + typeck_results.map(|x| &*tcx.arena.alloc(x)) + } } } @@ -880,6 +894,7 @@ key: ty::ParamEnvAnd<'tcx, ConstAlloc<'tcx>> ) -> Option> { desc { "destructure constant" } + remap_env_constness } /// Destructure a constant ADT or array into its variant index and its @@ -888,6 +903,7 @@ key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> mir::DestructuredConst<'tcx> { desc { "destructure constant" } + remap_env_constness } /// Dereference a constant reference or raw pointer and turn the result into a constant @@ -896,6 +912,7 @@ key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> &'tcx ty::Const<'tcx> { desc { "deref constant" } + remap_env_constness } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1100,26 +1117,32 @@ /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } + remap_env_constness } /// Query backing `TyS::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } + remap_env_constness } /// Query backing `TyS::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } + remap_env_constness } /// Query backing `TyS::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } + remap_env_constness } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } + remap_env_constness } /// Query backing `TyS::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } + remap_env_constness } /// Query backing `TyS::is_structural_eq_shallow`. @@ -1158,6 +1181,7 @@ key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result, ty::layout::LayoutError<'tcx>> { desc { "computing layout of `{}`", key.value } + remap_env_constness } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. @@ -1168,6 +1192,7 @@ key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } + remap_env_constness } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1179,6 +1204,7 @@ key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } + remap_env_constness } query dylib_dependency_formats(_: CrateNum) @@ -1385,16 +1411,14 @@ /// Given a crate and a trait, look up all impls of that trait in the crate. /// Return `(impl_id, self_ty)`. - query implementations_of_trait(_: (CrateNum, DefId)) - -> &'tcx [(DefId, Option)] { + query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { desc { "looking up implementations of a trait in a crate" } separate_provide_extern } /// Given a crate, look up all trait impls in that crate. /// Return `(impl_id, self_ty)`. - query all_trait_implementations(_: CrateNum) - -> &'tcx [(DefId, Option)] { + query all_trait_implementations(_: CrateNum) -> &'tcx [(DefId, Option)] { desc { "looking up all (?) trait implementations" } separate_provide_extern } @@ -1463,6 +1487,7 @@ key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> ty::inhabitedness::DefIdForest { desc { "computing the inhabitedness of `{:?}`", key } + remap_env_constness } query dep_kind(_: CrateNum) -> CrateDepKind { @@ -1485,9 +1510,8 @@ desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } - query get_lib_features(_: ()) -> LibFeatures { + query lib_features(_: ()) -> LibFeatures { storage(ArenaCacheSelector<'tcx>) - eval_always desc { "calculating the lib features map" } } query defined_lib_features(_: CrateNum) @@ -1583,11 +1607,11 @@ desc { "fetching all foreign CrateNum instances" } } - /// A vector of every trait accessible in the whole crate - /// (i.e., including those from subcrates). This is used only for - /// error reporting. - query all_traits(_: ()) -> &'tcx [DefId] { - desc { "fetching all foreign and local traits" } + /// A list of all traits in a crate, used by rustdoc and error reporting. + /// NOTE: Not named just `traits` due to a naming conflict. + query traits_in_crate(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all traits in a crate" } + separate_provide_extern } /// The list of symbols exported from the given crate. @@ -1643,20 +1667,23 @@ NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } - /// Do not call this query directly: invoke `normalize_erasing_regions` instead. - query normalize_generic_arg_after_erasing_regions( + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_generic_arg_after_erasing_regions( goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> - ) -> GenericArg<'tcx> { + ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } - /// Do not call this query directly: invoke `normalize_erasing_regions` instead. - query normalize_mir_const_after_erasing_regions( + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_mir_const_after_erasing_regions( goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> - ) -> mir::ConstantKind<'tcx> { + ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } query implied_outlives_bounds( @@ -1666,6 +1693,7 @@ NoSolution, > { desc { "computing implied outlives bounds for `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead. @@ -1676,6 +1704,7 @@ NoSolution, > { desc { "computing dropck types for `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or @@ -1703,6 +1732,7 @@ NoSolution, > { desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Eq` type-op @@ -1713,6 +1743,7 @@ NoSolution, > { desc { "evaluating `type_op_eq` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Subtype` type-op @@ -1723,6 +1754,7 @@ NoSolution, > { desc { "evaluating `type_op_subtype` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `ProvePredicate` type-op @@ -1743,6 +1775,7 @@ NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1753,6 +1786,7 @@ NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1763,6 +1797,7 @@ NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1773,6 +1808,7 @@ NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { @@ -1786,6 +1822,7 @@ goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { desc { "computing autoderef types for `{:?}`", goal } + remap_env_constness } query supported_target_features(_: CrateNum) -> FxHashMap> { @@ -1818,6 +1855,7 @@ key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> ) -> Result>, ErrorReported> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } + remap_env_constness } query resolve_instance_of_const_arg( @@ -1827,6 +1865,7 @@ "resolving instance of the const argument `{}`", ty::Instance::new(key.value.0.to_def_id(), key.value.2), } + remap_env_constness } query normalize_opaque_types(key: &'tcx ty::List>) -> &'tcx ty::List> { @@ -1841,6 +1880,7 @@ /// size, to account for partial initialisation. See #49298 for details.) query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "conservatively checking if {:?} is privately uninhabited", key } + remap_env_constness } query limits(key: ()) -> Limits { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/chalk.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/chalk.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/chalk.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/chalk.rs 2022-02-23 04:07:21.000000000 +0000 @@ -206,35 +206,36 @@ Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) } - fn intern_ty(&self, ty: chalk_ir::TyData) -> Self::InternedType { - Box::new(ty) + fn intern_ty(self, ty: chalk_ir::TyKind) -> Self::InternedType { + let flags = ty.compute_flags(self); + Box::new(chalk_ir::TyData { kind: ty, flags: flags }) } - fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { + fn ty_data<'a>(self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { ty } - fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { + fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { Box::new(lifetime) } fn lifetime_data<'a>( - &self, + self, lifetime: &'a Self::InternedLifetime, ) -> &'a chalk_ir::LifetimeData { &lifetime } - fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { + fn intern_const(self, constant: chalk_ir::ConstData) -> Self::InternedConst { Box::new(constant) } - fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { + fn const_data<'a>(self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { &constant } fn const_eq( - &self, + self, _ty: &Self::InternedType, c1: &Self::InternedConcreteConst, c2: &Self::InternedConcreteConst, @@ -242,143 +243,143 @@ c1 == c2 } - fn intern_generic_arg(&self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { + fn intern_generic_arg(self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { Box::new(data) } fn generic_arg_data<'a>( - &self, + self, data: &'a Self::InternedGenericArg, ) -> &'a chalk_ir::GenericArgData { &data } - fn intern_goal(&self, goal: chalk_ir::GoalData) -> Self::InternedGoal { + fn intern_goal(self, goal: chalk_ir::GoalData) -> Self::InternedGoal { Box::new(goal) } - fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { + fn goal_data<'a>(self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { &goal } fn intern_goals( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } - fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal] { + fn goals_data<'a>(self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal] { goals } fn intern_substitution( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn substitution_data<'a>( - &self, + self, substitution: &'a Self::InternedSubstitution, ) -> &'a [chalk_ir::GenericArg] { substitution } fn intern_program_clause( - &self, + self, data: chalk_ir::ProgramClauseData, ) -> Self::InternedProgramClause { Box::new(data) } fn program_clause_data<'a>( - &self, + self, clause: &'a Self::InternedProgramClause, ) -> &'a chalk_ir::ProgramClauseData { &clause } fn intern_program_clauses( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn program_clauses_data<'a>( - &self, + self, clauses: &'a Self::InternedProgramClauses, ) -> &'a [chalk_ir::ProgramClause] { clauses } fn intern_quantified_where_clauses( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn quantified_where_clauses_data<'a>( - &self, + self, clauses: &'a Self::InternedQuantifiedWhereClauses, ) -> &'a [chalk_ir::QuantifiedWhereClause] { clauses } fn intern_generic_arg_kinds( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn variable_kinds_data<'a>( - &self, + self, parameter_kinds: &'a Self::InternedVariableKinds, ) -> &'a [chalk_ir::VariableKind] { parameter_kinds } fn intern_canonical_var_kinds( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn canonical_var_kinds_data<'a>( - &self, + self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, ) -> &'a [chalk_ir::CanonicalVarKind] { canonical_var_kinds } fn intern_constraints( - &self, + self, data: impl IntoIterator>, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn constraints_data<'a>( - &self, + self, constraints: &'a Self::InternedConstraints, ) -> &'a [chalk_ir::InEnvironment>] { constraints } fn intern_variances( - &self, + self, data: impl IntoIterator>, ) -> Result { data.into_iter().collect::, _>>() } fn variances_data<'a>( - &self, + self, variances: &'a Self::InternedVariances, ) -> &'a [chalk_ir::Variance] { variances diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,9 +23,7 @@ use smallvec::SmallVec; use std::borrow::Cow; -use std::fmt; use std::hash::{Hash, Hasher}; -use std::ops::Deref; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; @@ -80,38 +78,14 @@ /// The reason why we incurred this obligation; used for error reporting. /// -/// As the happy path does not care about this struct, storing this on the heap -/// ends up increasing performance. +/// Non-misc `ObligationCauseCode`s are stored on the heap. This gives the +/// best trade-off between keeping the type small (which makes copies cheaper) +/// while not doing too many heap allocations. /// /// We do not want to intern this as there are a lot of obligation causes which /// only live for a short period of time. -#[derive(Clone, PartialEq, Eq, Hash, Lift)] -pub struct ObligationCause<'tcx> { - /// `None` for `ObligationCause::dummy`, `Some` otherwise. - data: Option>>, -} - -const DUMMY_OBLIGATION_CAUSE_DATA: ObligationCauseData<'static> = - ObligationCauseData { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }; - -// Correctly format `ObligationCause::dummy`. -impl<'tcx> fmt::Debug for ObligationCause<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ObligationCauseData::fmt(self, f) - } -} - -impl Deref for ObligationCause<'tcx> { - type Target = ObligationCauseData<'tcx>; - - #[inline(always)] - fn deref(&self) -> &Self::Target { - self.data.as_deref().unwrap_or(&DUMMY_OBLIGATION_CAUSE_DATA) - } -} - #[derive(Clone, Debug, PartialEq, Eq, Lift)] -pub struct ObligationCauseData<'tcx> { +pub struct ObligationCause<'tcx> { pub span: Span, /// The ID of the fn body that triggered this obligation. This is @@ -122,17 +96,25 @@ /// information. pub body_id: hir::HirId, - pub code: ObligationCauseCode<'tcx>, + /// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of + /// the time). `Some` otherwise. + code: Option>>, } -impl Hash for ObligationCauseData<'_> { +// This custom hash function speeds up hashing for `Obligation` deduplication +// greatly by skipping the `code` field, which can be large and complex. That +// shouldn't affect hash quality much since there are several other fields in +// `Obligation` which should be unique enough, especially the predicate itself +// which is hashed as an interned pointer. See #90996. +impl Hash for ObligationCause<'_> { fn hash(&self, state: &mut H) { self.body_id.hash(state); self.span.hash(state); - std::mem::discriminant(&self.code).hash(state); } } +const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation; + impl<'tcx> ObligationCause<'tcx> { #[inline] pub fn new( @@ -140,28 +122,32 @@ body_id: hir::HirId, code: ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { - ObligationCause { data: Some(Lrc::new(ObligationCauseData { span, body_id, code })) } + ObligationCause { + span, + body_id, + code: if code == MISC_OBLIGATION_CAUSE_CODE { None } else { Some(Lrc::new(code)) }, + } } pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { ObligationCause::new(span, body_id, MiscObligation) } - pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { - ObligationCause::new(span, hir::CRATE_HIR_ID, MiscObligation) - } - #[inline(always)] pub fn dummy() -> ObligationCause<'tcx> { - ObligationCause { data: None } + ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: None } + } + + pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { + ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: None } } - pub fn make_mut(&mut self) -> &mut ObligationCauseData<'tcx> { - Lrc::make_mut(self.data.get_or_insert_with(|| Lrc::new(DUMMY_OBLIGATION_CAUSE_DATA))) + pub fn make_mut_code(&mut self) -> &mut ObligationCauseCode<'tcx> { + Lrc::make_mut(self.code.get_or_insert_with(|| Lrc::new(MISC_OBLIGATION_CAUSE_CODE))) } pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { - match self.code { + match *self.code() { ObligationCauseCode::CompareImplMethodObligation { .. } | ObligationCauseCode::MainFunctionType | ObligationCauseCode::StartFunctionType => { @@ -174,6 +160,18 @@ _ => self.span, } } + + #[inline] + pub fn code(&self) -> &ObligationCauseCode<'tcx> { + self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE) + } + + pub fn clone_code(&self) -> Lrc> { + match &self.code { + Some(code) => code.clone(), + None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE), + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] @@ -348,6 +346,12 @@ /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, + AwaitableExpr(Option), + + ForLoopIterator, + + QuestionMark, + /// Well-formed checking. If a `WellFormedLoc` is provided, /// then it will be used to eprform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. @@ -587,18 +591,18 @@ pub fn borrow_nested_obligations(&self) -> &[N] { match &self { ImplSource::UserDefined(i) => &i.nested[..], - ImplSource::Param(n, _) => &n[..], - ImplSource::Builtin(i) => &i.nested[..], - ImplSource::AutoImpl(d) => &d.nested[..], - ImplSource::Closure(c) => &c.nested[..], - ImplSource::Generator(c) => &c.nested[..], - ImplSource::Object(d) => &d.nested[..], - ImplSource::FnPointer(d) => &d.nested[..], + ImplSource::Param(n, _) => &n, + ImplSource::Builtin(i) => &i.nested, + ImplSource::AutoImpl(d) => &d.nested, + ImplSource::Closure(c) => &c.nested, + ImplSource::Generator(c) => &c.nested, + ImplSource::Object(d) => &d.nested, + ImplSource::FnPointer(d) => &d.nested, ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) | ImplSource::Pointee(ImplSourcePointeeData) | ImplSource::ConstDrop(ImplSourceConstDropData) => &[], - ImplSource::TraitAlias(d) => &d.nested[..], - ImplSource::TraitUpcasting(d) => &d.nested[..], + ImplSource::TraitAlias(d) => &d.nested, + ImplSource::TraitUpcasting(d) => &d.nested, } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/select.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/select.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/select.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/select.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,14 +12,12 @@ use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< - (ty::ConstnessAnd>>, ty::ImplPolarity), + ty::ParamEnvAnd<'tcx, ty::TraitPredicate<'tcx>>, SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = Cache< - (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd>>, ty::ImplPolarity), - EvaluationResult, ->; +pub type EvaluationCache<'tcx> = + Cache>, EvaluationResult>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes @@ -103,7 +101,7 @@ /// `false` if there are no *further* obligations. has_nested: bool, }, - ParamCandidate((ty::ConstnessAnd>, ty::ImplPolarity)), + ParamCandidate(ty::PolyTraitPredicate<'tcx>), ImplCandidate(DefId), AutoImplCandidate(DefId), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/specialization_graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/specialization_graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/specialization_graph.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/specialization_graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -216,7 +216,7 @@ /// /// Returns `Err` if an error was reported while building the specialization /// graph. -pub fn ancestors( +pub fn ancestors<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, start_from_impl: DefId, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/structural_impls.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/structural_impls.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/structural_impls.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/structural_impls.rs 2022-02-23 04:07:21.000000000 +0000 @@ -74,7 +74,7 @@ } } -impl fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { +impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/traits/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -26,9 +26,9 @@ .predicates .into_iter() .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() }) - .map(|t| t.value) + .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); self.stack.extend(supertrait_refs); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adjustment.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adjustment.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adjustment.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adjustment.rs 2022-02-23 04:07:21.000000000 +0000 @@ -83,7 +83,7 @@ pub target: Ty<'tcx>, } -impl Adjustment<'tcx> { +impl<'tcx> Adjustment<'tcx> { pub fn is_region_borrow(&self) -> bool { matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..))) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adt.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adt.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adt.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/adt.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,11 +7,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_serialize::{self, Encodable, Encoder}; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; use rustc_target::abi::VariantIdx; @@ -20,7 +19,7 @@ use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::ops::Range; -use std::{ptr, str}; +use std::str; use super::{ Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, @@ -30,7 +29,7 @@ pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; /// Indicates whether the ADT is an enum. @@ -64,6 +63,31 @@ /// Moreover, Rust only allows recursive data types through indirection. /// /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type +/// +/// # Recursive types +/// +/// It may seem impossible to represent recursive types using [`Ty`], +/// since [`TyKind::Adt`] includes [`AdtDef`], which includes its fields, +/// creating a cycle. However, `AdtDef` does not actually include the *types* +/// of its fields; it includes just their [`DefId`]s. +/// +/// [`TyKind::Adt`]: ty::TyKind::Adt +/// +/// For example, the following type: +/// +/// ``` +/// struct S { x: Box } +/// ``` +/// +/// is essentially represented with [`Ty`] as the following pseudocode: +/// +/// ``` +/// struct S { x } +/// ``` +/// +/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId` +/// can be used with [`TyCtxt::type_of()`] to get the type of the field. +#[derive(TyEncodable, TyDecodable)] pub struct AdtDef { /// The `DefId` of the struct, enum or union item. pub did: DefId, @@ -89,26 +113,23 @@ } } +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `PartialEq` only based on `did`. impl PartialEq for AdtDef { - // `AdtDef`s are always interned, and this is part of `TyS` equality. #[inline] fn eq(&self, other: &Self) -> bool { - ptr::eq(self, other) + self.did == other.did } } impl Eq for AdtDef {} +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `Hash` only based on `did`. impl Hash for AdtDef { #[inline] fn hash(&self, s: &mut H) { - (self as *const AdtDef).hash(s) - } -} - -impl Encodable for AdtDef { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.did.encode(s) + self.did.hash(s) } } @@ -137,7 +158,7 @@ } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] pub enum AdtKind { Struct, Union, @@ -314,6 +335,22 @@ /// Whether the ADT lacks fields. Note that this includes uninhabited enums, /// e.g., `enum Void {}` is considered payload free as well. pub fn is_payloadfree(&self) -> bool { + // Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621). + // This would disallow the following kind of enum from being casted into integer. + // ``` + // enum Enum { + // Foo() = 1, + // Bar{} = 2, + // Baz = 3, + // } + // ``` + if self + .variants + .iter() + .any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const) + { + return false; + } self.variants.iter().all(|v| v.fields.is_empty()) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/assoc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/assoc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/assoc.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/assoc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -139,7 +139,7 @@ /// Multiple items may have the same name if they are in different `Namespace`s. For example, /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*` /// methods below if you know which item you are looking for. - pub fn filter_by_name( + pub fn filter_by_name<'a>( &'a self, tcx: TyCtxt<'a>, ident: Ident, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/closure.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/closure.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/closure.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/closure.rs 2022-02-23 04:07:21.000000000 +0000 @@ -156,7 +156,7 @@ pub mutability: hir::Mutability, } -impl CapturedPlace<'tcx> { +impl<'tcx> CapturedPlace<'tcx> { pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> String { place_to_string_for_capture(tcx, &self.place) } @@ -328,7 +328,7 @@ pub capture_kind: UpvarCapture<'tcx>, } -pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { +pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { let mut curr_string: String = match place.base { HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/codec.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/codec.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/codec.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/codec.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,7 +16,6 @@ use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::Span; use std::hash::Hash; @@ -76,7 +75,11 @@ } /// Encode the given value or a previously cached shorthand. -pub fn encode_with_shorthand(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error> +pub fn encode_with_shorthand<'tcx, E, T, M>( + encoder: &mut E, + value: &T, + cache: M, +) -> Result<(), E::Error> where E: TyEncoder<'tcx>, M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap, @@ -156,7 +159,8 @@ &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::AdtDef } pub trait TyDecoder<'tcx>: Decoder { @@ -308,13 +312,6 @@ } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - let def_id = >::decode(decoder)?; - Ok(decoder.tcx().adt_def(def_id)) - } -} - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; @@ -399,7 +396,8 @@ &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, - &'tcx ty::List + &'tcx ty::List, + &'tcx ty::AdtDef } #[macro_export] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/int.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/int.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/int.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/int.rs 2022-02-23 04:07:21.000000000 +0000 @@ -234,7 +234,7 @@ } #[inline] - pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Result { + pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result { Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/valtree.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/valtree.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/valtree.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/consts/valtree.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,7 +27,7 @@ Branch(&'tcx [ValTree<'tcx>]), } -impl ValTree<'tcx> { +impl<'tcx> ValTree<'tcx> { pub fn zst() -> Self { Self::Branch(&[]) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/context.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/context.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/context.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/context.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,7 +5,6 @@ use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; -use crate::middle; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; @@ -113,6 +112,7 @@ const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, Layout>, + adt_def: InternedSet<'tcx, AdtDef>, } impl<'tcx> CtxtInterners<'tcx> { @@ -133,6 +133,7 @@ const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), + adt_def: Default::default(), } } @@ -825,7 +826,7 @@ /// Canonicalized user type annotation. pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>; -impl CanonicalUserType<'tcx> { +impl<'tcx> CanonicalUserType<'tcx> { /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`, /// i.e., each thing is mapped to a canonical variable with the same index. pub fn is_identity(&self) -> bool { @@ -1079,7 +1080,7 @@ variants: IndexVec, repr: ReprOptions, ) -> &'tcx ty::AdtDef { - self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) + self.intern_adt_def(ty::AdtDef::new(self, did, kind, variants, repr)) } /// Allocates a read-only byte or string literal for `mir::interpret`. @@ -1112,7 +1113,11 @@ }; debug!("layout_scalar_valid_range: attr={:?}", attr); if let Some( - &[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })], + &[ + ast::NestedMetaItem::Literal(ast::Lit { + kind: ast::LitKind::Int(a, _), .. + }), + ], ) = attr.meta_item_list().as_deref() { Bound::Included(a) @@ -1213,12 +1218,8 @@ } pub fn consider_optimizing String>(self, msg: T) -> bool { - let cname = self.crate_name(LOCAL_CRATE).as_str(); - self.sess.consider_optimizing(&cname, msg) - } - - pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures { - self.get_lib_features(()) + let cname = self.crate_name(LOCAL_CRATE); + self.sess.consider_optimizing(cname.as_str(), msg) } /// Obtain all lang items of this crate and all dependencies (recursively) @@ -1482,40 +1483,8 @@ scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - let hir_output = match self.hir().get(hir_id) { - Node::Item(hir::Item { - kind: - ItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - .., - ), - .. - }) - | Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - _, - ), - .. - }) - | Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - _, - ), - .. - }) => ty, + let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) { + Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty, _ => return vec![], }; @@ -1608,6 +1577,12 @@ pub fn const_eval_limit(self) -> Limit { self.limits(()).const_eval_limit } + + pub fn all_traits(self) -> impl Iterator + 'tcx { + iter::once(LOCAL_CRATE) + .chain(self.crates(()).iter().copied()) + .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied()) + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1926,7 +1901,7 @@ pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx { struct DebugStats<'tcx>(TyCtxt<'tcx>); - impl std::fmt::Debug for DebugStats<'tcx> { + impl<'tcx> std::fmt::Debug for DebugStats<'tcx> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { sty_debug_print!( fmt, @@ -2090,6 +2065,7 @@ const_: mk_const(Const<'tcx>), const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), + adt_def: intern_adt_def(AdtDef), } macro_rules! slice_interners { @@ -2744,7 +2720,7 @@ } } -impl TyCtxtAt<'tcx> { +impl<'tcx> TyCtxtAt<'tcx> { /// 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> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/diagnostics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/diagnostics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/diagnostics.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/diagnostics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,11 +1,17 @@ //! Diagnostics related methods for `TyS`. +use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::TyKind::*; -use crate::ty::{InferTy, TyCtxt, TyS}; +use crate::ty::{ + ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, + ProjectionTy, TyCtxt, TyS, TypeAndMut, +}; + use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_span::Span; impl<'tcx> TyS<'tcx> { /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. @@ -62,16 +68,55 @@ /// Whether the type can be safely suggested during error recovery. pub fn is_suggestable(&self) -> bool { - !matches!( - self.kind(), + fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool { + match arg.unpack() { + GenericArgKind::Type(ty) => ty.is_suggestable(), + GenericArgKind::Const(c) => const_is_suggestable(c.val), + _ => true, + } + } + + fn const_is_suggestable(kind: ConstKind<'_>) -> bool { + match kind { + ConstKind::Infer(..) + | ConstKind::Bound(..) + | ConstKind::Placeholder(..) + | ConstKind::Error(..) => false, + _ => true, + } + } + + // FIXME(compiler-errors): Some types are still not good to suggest, + // specifically references with lifetimes within the function. Not + //sure we have enough information to resolve whether a region is + // temporary, so I'll leave this as a fixme. + + match self.kind() { Opaque(..) - | FnDef(..) - | FnPtr(..) - | Dynamic(..) - | Closure(..) - | Infer(..) - | Projection(..) - ) + | FnDef(..) + | Closure(..) + | Infer(..) + | Generator(..) + | GeneratorWitness(..) + | Bound(_, _) + | Placeholder(_) + | Error(_) => false, + Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() { + ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { + substs.iter().all(generic_arg_is_suggestible) + } + ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => { + ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible) + } + _ => true, + }), + Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) | Tuple(args) => { + args.iter().all(generic_arg_is_suggestible) + } + Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), + Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val), + _ => true, + } } } @@ -270,7 +315,7 @@ // `where` clause instead of `trait Base: Super`. && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) { - if let Some(bounds_span) = param.bounds_span() { + if let Some(span) = param.bounds_span_for_suggestions() { // If user has provided some bounds, suggest restricting them: // // fn foo(t: T) { ... } @@ -284,7 +329,7 @@ // -- // | // replace with: `T: Bar +` - suggest_restrict(bounds_span.shrink_to_hi()); + suggest_restrict(span); } else { // If user hasn't provided any bounds, suggest adding a new one: // @@ -432,3 +477,22 @@ hir::intravisit::walk_ty(self, ty); } } + +/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. +pub struct StaticLifetimeVisitor<'tcx>(pub Vec, pub crate::hir::map::Map<'tcx>); + +impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { + if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = + lt.name + { + self.0.push(lt.span); + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/erase_regions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/erase_regions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/erase_regions.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/erase_regions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -37,7 +37,7 @@ tcx: TyCtxt<'tcx>, } -impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { +impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/error.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/error.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/error.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/error.rs 2022-02-23 04:07:21.000000000 +0000 @@ -118,8 +118,7 @@ ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"), TupleSize(values) => write!( f, - "expected a tuple with {} element{}, \ - found one with {} element{}", + "expected a tuple with {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, @@ -127,8 +126,7 @@ ), FixedArraySize(values) => write!( f, - "expected an array with a fixed size of {} element{}, \ - found one with {} element{}", + "expected an array with a fixed size of {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, @@ -521,7 +519,7 @@ proj_ty, values, body_owner_def_id, - &cause.code, + cause.code(), ); } (_, ty::Projection(proj_ty)) => { @@ -777,9 +775,7 @@ if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { let opaque_local_def_id = def_id.as_local(); let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id { - let hir = self.hir(); - let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id); - match &hir.expect_item(opaque_hir_id).kind { + match &self.hir().expect_item(opaque_local_def_id).kind { hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty, _ => bug!("The HirId comes from a `ty::Opaque`"), } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fast_reject.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fast_reject.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fast_reject.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fast_reject.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,4 @@ +use crate::mir::Mutability; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -19,7 +20,7 @@ #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] pub enum SimplifiedTypeGen where - D: Copy + Debug + Ord + Eq, + D: Copy + Debug + Eq, { BoolSimplifiedType, CharSimplifiedType, @@ -27,9 +28,12 @@ UintSimplifiedType(ty::UintTy), FloatSimplifiedType(ty::FloatTy), AdtSimplifiedType(D), + ForeignSimplifiedType(D), StrSimplifiedType, ArraySimplifiedType, - PtrSimplifiedType, + SliceSimplifiedType, + RefSimplifiedType(Mutability), + PtrSimplifiedType(Mutability), NeverSimplifiedType, TupleSimplifiedType(usize), /// A trait object, all of whose components are markers @@ -42,22 +46,48 @@ OpaqueSimplifiedType(D), FunctionSimplifiedType(usize), ParameterSimplifiedType, - ForeignSimplifiedType(DefId), } -/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. -/// The idea is to get something simple that we can use to quickly decide if two types could unify -/// during method lookup. -/// -/// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This -/// is useful when those type parameters would be instantiated with fresh type variables, since -/// then we can't say much about whether two types would unify. Put another way, -/// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they -/// are to be considered bound. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum SimplifyParams { + Yes, + No, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum StripReferences { + Yes, + No, +} + +/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. +/// +/// The idea is to get something simple that we can use to quickly decide if two types could unify, +/// for example during method lookup. +/// +/// A special case here are parameters and projections. Projections can be normalized to +/// a different type, meaning that `::Assoc` and `u8` can be unified, even though +/// their outermost layer is different while parameters like `T` of impls are later replaced +/// with an inference variable, which then also allows unification with other types. +/// +/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections², +/// the reasoning for this can be seen at the places doing this. +/// +/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best +/// way to skip some unhelpful suggestions. +/// +/// ¹ meaning that if two outermost layers are different, then the whole types are also different. +/// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during +/// candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even +/// though `_` can be inferred to a concrete type later at which point a concrete impl +/// could actually apply. After experimenting for about an hour I wasn't able to cause any issues +/// this way so I am not going to change this until we actually find an issue as I am really +/// interesting in getting an actual test for this. pub fn simplify_type( tcx: TyCtxt<'_>, ty: Ty<'_>, - can_simplify_params: bool, + can_simplify_params: SimplifyParams, + strip_references: StripReferences, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -67,19 +97,24 @@ ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)), ty::Str => Some(StrSimplifiedType), - ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), - ty::RawPtr(_) => Some(PtrSimplifiedType), + ty::Array(..) => Some(ArraySimplifiedType), + ty::Slice(..) => Some(SliceSimplifiedType), + ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { Some(TraitSimplifiedType(principal_def_id)) } _ => Some(MarkerTraitObjectSimplifiedType), }, - ty::Ref(_, ty, _) => { - // since we introduce auto-refs during method lookup, we - // just treat &T and T as equivalent from the point of - // view of possibly unifying - simplify_type(tcx, ty, can_simplify_params) + ty::Ref(_, ty, mutbl) => { + if strip_references == StripReferences::Yes { + // For diagnostics, when recommending similar impls we want to + // recommend impls even when there is a reference mismatch, + // so we treat &T and T equivalently in that case. + simplify_type(tcx, ty, can_simplify_params, strip_references) + } else { + Some(RefSimplifiedType(mutbl)) + } } ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), @@ -90,7 +125,7 @@ ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())), ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Projection(_) | ty::Param(_) => { - if can_simplify_params { + if can_simplify_params == SimplifyParams::Yes { // In normalized types, projections don't unify with // anything. when lazy normalization happens, this // will change. It would still be nice to have a way @@ -108,6 +143,18 @@ } impl SimplifiedTypeGen { + pub fn def(self) -> Option { + match self { + AdtSimplifiedType(d) + | ForeignSimplifiedType(d) + | TraitSimplifiedType(d) + | ClosureSimplifiedType(d) + | GeneratorSimplifiedType(d) + | OpaqueSimplifiedType(d) => Some(d), + _ => None, + } + } + pub fn map_def(self, map: F) -> SimplifiedTypeGen where F: Fn(D) -> U, @@ -120,9 +167,12 @@ UintSimplifiedType(t) => UintSimplifiedType(t), FloatSimplifiedType(t) => FloatSimplifiedType(t), AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), + ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)), StrSimplifiedType => StrSimplifiedType, ArraySimplifiedType => ArraySimplifiedType, - PtrSimplifiedType => PtrSimplifiedType, + SliceSimplifiedType => SliceSimplifiedType, + RefSimplifiedType(m) => RefSimplifiedType(m), + PtrSimplifiedType(m) => PtrSimplifiedType(m), NeverSimplifiedType => NeverSimplifiedType, MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), @@ -133,7 +183,6 @@ OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), FunctionSimplifiedType(n) => FunctionSimplifiedType(n), ParameterSimplifiedType => ParameterSimplifiedType, - ForeignSimplifiedType(d) => ForeignSimplifiedType(d), } } } @@ -149,12 +198,13 @@ | CharSimplifiedType | StrSimplifiedType | ArraySimplifiedType - | PtrSimplifiedType + | SliceSimplifiedType | NeverSimplifiedType | ParameterSimplifiedType | MarkerTraitObjectSimplifiedType => { // nothing to do } + RefSimplifiedType(m) | PtrSimplifiedType(m) => m.hash_stable(hcx, hasher), IntSimplifiedType(t) => t.hash_stable(hcx, hasher), UintSimplifiedType(t) => t.hash_stable(hcx, hasher), FloatSimplifiedType(t) => t.hash_stable(hcx, hasher), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/flags.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/flags.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/flags.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/flags.rs 2022-02-23 04:07:21.000000000 +0000 @@ -22,7 +22,7 @@ result } - pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { + pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -216,7 +216,7 @@ } } - fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { + fn add_predicate(&mut self, binder: ty::Binder<'_, ty::PredicateKind<'_>>) { self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); } @@ -310,7 +310,7 @@ } } - fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'tcx, P>) { + fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'_, P>) { // The generic arguments of unevaluated consts are a bit special, // see the `rustc-dev-guide` for more information. // diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fold.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fold.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fold.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/fold.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,9 +46,30 @@ /// /// To implement this conveniently, use the derive macro located in `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - fn super_fold_with>(self, folder: &mut F) -> Self; - fn fold_with>(self, folder: &mut F) -> Self { - self.super_fold_with(folder) + /// Consumers may find this more convenient to use with infallible folders than + /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the + /// provided default definition delegates. Implementors **should not** override + /// this provided default definition, to ensure that the two methods are coherent + /// (provide a definition of `try_super_fold_with` instead). + fn super_fold_with>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() + } + /// Consumers may find this more convenient to use with infallible folders than + /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided + /// default definition delegates. Implementors **should not** override this + /// provided default definition, to ensure that the two methods are coherent + /// (provide a definition of `try_fold_with` instead). + fn fold_with>(self, folder: &mut F) -> Self { + self.try_fold_with(folder).into_ok() + } + + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result; + + fn try_fold_with>(self, folder: &mut F) -> Result { + self.try_super_fold_with(folder) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; @@ -178,9 +199,9 @@ } } -impl TypeFoldable<'tcx> for hir::Constness { - fn super_fold_with>(self, _: &mut F) -> Self { - self +impl<'tcx> TypeFoldable<'tcx> for hir::Constness { + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -192,37 +213,152 @@ /// default implementation that does an "identity" fold. Within each /// identity fold, it should invoke `foo.fold_with(self)` to fold each /// sub-item. +/// +/// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] +/// associated type is something other than the default, never), +/// [`FallibleTypeFolder`] should be implemented manually; otherwise, +/// a blanket implementation of [`FallibleTypeFolder`] will defer to +/// the infallible methods of this trait to ensure that the two APIs +/// are coherent. pub trait TypeFolder<'tcx>: Sized { + type Error = !; + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, + Self: TypeFolder<'tcx, Error = !>, { t.super_fold_with(self) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { t.super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { c.super_fold_with(self) } - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { p.super_fold_with(self) } - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { bug!("most type folders should not be folding MIR datastructures: {:?}", c) } } +/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a +/// method defined for every foldable type. Each of these has a +/// default implementation that does an "identity" fold. Within each +/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each +/// sub-item. +/// +/// A blanket implementation of this trait (that defers to the relevant +/// method of [`TypeFolder`]) is provided for all infallible folders in +/// order to ensure the two APIs are coherent. +pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> { + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: TypeFoldable<'tcx>, + { + t.try_super_fold_with(self) + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + t.try_super_fold_with(self) + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + r.try_super_fold_with(self) + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + c.try_super_fold_with(self) + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + p.try_super_fold_with(self) + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + bug!("most type folders should not be folding MIR datastructures: {:?}", c) + } +} + +// Blanket implementation of fallible trait for infallible folders +// delegates to infallible methods to prevent incoherence +impl<'tcx, F> FallibleTypeFolder<'tcx> for F +where + F: TypeFolder<'tcx, Error = !>, +{ + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: TypeFoldable<'tcx>, + { + Ok(self.fold_binder(t)) + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + Ok(self.fold_ty(t)) + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + Ok(self.fold_region(r)) + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + Ok(self.fold_const(c)) + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + Ok(self.fold_predicate(p)) + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + Ok(self.fold_mir_const(c)) + } +} + pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs @@ -924,13 +1060,13 @@ amount: u32, } -impl Shifter<'tcx> { +impl<'tcx> Shifter<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self { Shifter { tcx, current_index: ty::INNERMOST, amount } } } -impl TypeFolder<'tcx> for Shifter<'tcx> { +impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } @@ -1121,7 +1257,7 @@ flags: ty::TypeFlags, } -impl std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { +impl<'tcx> std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.flags.fmt(fmt) } @@ -1318,7 +1454,7 @@ just_constrained: bool, } -impl LateBoundRegionsCollector<'tcx> { +impl<'tcx> LateBoundRegionsCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self { LateBoundRegionsCollector { tcx, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/generics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/generics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/generics.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/generics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -24,13 +24,11 @@ GenericParamDefKind::Const { .. } => "constant", } } - pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { + pub fn to_ord(&self) -> ast::ParamKindOrd { match self { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const { .. } => { - ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } - } + GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs 2022-02-23 04:07:21.000000000 +0000 @@ -30,7 +30,7 @@ /// Tests whether a slice of roots contains a given DefId. #[inline] -fn slice_contains(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool { +fn slice_contains<'tcx>(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool { slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id)) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/instance.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/instance.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/instance.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/instance.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,7 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; +use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use std::fmt; @@ -575,6 +576,23 @@ } } + #[inline(always)] + pub fn try_subst_mir_and_normalize_erasing_regions( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + v: T, + ) -> Result> + where + T: TypeFoldable<'tcx> + Clone, + { + if let Some(substs) = self.substs_for_mir_body() { + tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v) + } else { + tcx.try_normalize_erasing_regions(param_env, v) + } + } + /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by /// identity parameters if they are determined to be unused in `instance.def`. pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { @@ -617,7 +635,7 @@ tcx: TyCtxt<'tcx>, } - impl ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> { + impl<'tcx> ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/layout.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/layout.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/layout.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/layout.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; +use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast as ast; @@ -167,7 +168,7 @@ /// Return an *integer* type matching this primitive. /// Useful in particular when dealing with enum discriminants. #[inline] - fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { Int(i, signed) => i.to_ty(tcx, signed), Pointer => tcx.types.usize, @@ -199,6 +200,7 @@ pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), + NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } impl<'tcx> fmt::Display for LayoutError<'tcx> { @@ -208,16 +210,24 @@ LayoutError::SizeOverflow(ty) => { write!(f, "values of the type `{}` are too big for the current architecture", ty) } + LayoutError::NormalizationFailure(t, e) => write!( + f, + "unable to determine layout for `{}` because `{}` cannot be normalized", + t, + e.get_type_for_failure() + ), } } } +#[instrument(skip(tcx, query), level = "debug")] fn layout_of<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Result, LayoutError<'tcx>> { ty::tls::with_related_context(tcx, move |icx| { let (param_env, ty) = query.into_parts(); + debug!(?ty); if !tcx.recursion_limit().value_within_limit(icx.layout_depth) { tcx.sess.fatal(&format!("overflow representing the type `{}`", ty)); @@ -229,7 +239,18 @@ ty::tls::enter_context(&icx, |_| { let param_env = param_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; - let ty = tcx.normalize_erasing_regions(param_env, ty); + + // FIXME: We might want to have two different versions of `layout_of`: + // One that can be called after typecheck has completed and can use + // `normalize_erasing_regions` here and another one that can be called + // before typecheck has completed and uses `try_normalize_erasing_regions`. + let ty = match tcx.try_normalize_erasing_regions(param_env, ty) { + Ok(t) => t, + Err(normalization_error) => { + return Err(LayoutError::NormalizationFailure(ty, normalization_error)); + } + }; + if ty != unnormalized_ty { // Ensure this layout is also cached for the normalized type. return tcx.layout_of(param_env.and(ty)); @@ -326,10 +347,6 @@ let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); - // `ReprOptions.layout_seed` is a deterministic seed that we can use to - // randomize field ordering with - let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); - let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = @@ -343,6 +360,10 @@ // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee if repr.can_randomize_type_layout() { + // `ReprOptions.layout_seed` is a deterministic seed that we can use to + // randomize field ordering with + let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); + // Shuffle the ordering of the fields optimizing.shuffle(&mut rng); @@ -512,7 +533,7 @@ } } - if sized && fields.iter().any(|f| f.abi.is_uninhabited()) { + if fields.iter().any(|f| f.abi.is_uninhabited()) { abi = Abi::Uninhabited; } @@ -2174,9 +2195,9 @@ } } -impl> LayoutOf<'tcx> for C {} +impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {} -impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { +impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -2185,7 +2206,7 @@ } } -impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { +impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -2261,7 +2282,7 @@ TyAndLayout(TyAndLayout<'tcx>), } - fn field_ty_or_layout( + fn field_ty_or_layout<'tcx>( this: TyAndLayout<'tcx>, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), i: usize, @@ -2560,9 +2581,12 @@ // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. - fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. - let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); + fn fn_sig_for_fn_abi( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> ty::PolyFnSig<'tcx> { + let ty = self.ty(tcx, param_env); match *ty.kind() { ty::FnDef(..) => { // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering @@ -2703,7 +2727,7 @@ /// with `-Cpanic=abort` will look like they can't unwind when in fact they /// might (from a foreign exception or similar). #[inline] -pub fn fn_can_unwind( +pub fn fn_can_unwind<'tcx>( tcx: TyCtxt<'tcx>, codegen_fn_attr_flags: CodegenFnAttrFlags, abi: SpecAbi, @@ -2821,7 +2845,7 @@ AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl From> for FnAbiError<'tcx> { +impl<'tcx> From> for FnAbiError<'tcx> { fn from(err: LayoutError<'tcx>) -> Self { Self::Layout(err) } @@ -2921,7 +2945,7 @@ } } -impl> FnAbiOf<'tcx> for C {} +impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} fn fn_abi_of_fn_ptr<'tcx>( tcx: TyCtxt<'tcx>, @@ -2944,7 +2968,7 @@ ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { let (param_env, (instance, extra_args)) = query.into_parts(); - let sig = instance.fn_sig_for_fn_abi(tcx); + let sig = instance.fn_sig_for_fn_abi(tcx, param_env); let caller_location = if instance.def.requires_caller_location(tcx) { Some(tcx.caller_location_ty()) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/list.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/list.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/list.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/list.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,5 @@ use crate::arena::Arena; - use rustc_serialize::{Encodable, Encoder}; - use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -12,49 +10,69 @@ use std::ptr; use std::slice; -extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring references to it be wide - /// pointers. - type OpaqueListContents; -} - -/// A wrapper for slices with the additional invariant -/// that the slice is interned and no other slice with -/// the same contents can exist in the same context. -/// This means we can use pointer for both -/// equality comparisons and hashing. -/// -/// Unlike slices, the types contained in `List` are expected to be `Copy` -/// and iterating over a `List` returns `T` instead of a reference. -/// -/// Note: `Slice` was already taken by the `Ty`. +/// `List` is a bit like `&[T]`, but with some critical differences. +/// - IMPORTANT: Every `List` is *required* to have unique contents. The +/// type's correctness relies on this, *but it does not enforce it*. +/// Therefore, any code that creates a `List` must ensure uniqueness +/// itself. In practice this is achieved by interning. +/// - The length is stored within the `List`, so `&List` is a thin +/// pointer. +/// - Because of this, you cannot get a `List` that is a sub-list of another +/// `List`. You can get a sub-slice `&[T]`, however. +/// - `List` can be used with `CopyTaggedPtr`, which is useful within +/// structs whose size must be minimized. +/// - Because of the uniqueness assumption, we can use the address of a +/// `List` for faster equality comparisons and hashing. +/// - `T` must be `Copy`. This lets `List` be stored in a dropless arena and +/// iterators return a `T` rather than a `&T`. +/// - `T` must not be zero-sized. #[repr(C)] pub struct List { len: usize, + + /// Although this claims to be a zero-length array, in practice `len` + /// elements are actually present. data: [T; 0], + opaque: OpaqueListContents, } -unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - #[inline] - fn into_usize(self) -> usize { - self as *const List as usize - } - #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - &*(ptr as *const List) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - // Self: Copy so this is fine - let ptr = Self::from_usize(ptr); - f(&ptr) - } +extern "C" { + /// A dummy type used to force `List` to be unsized while not requiring + /// references to it be wide pointers. + type OpaqueListContents; } -unsafe impl Sync for List {} +impl List { + /// Returns a reference to the (unique, static) empty list. + #[inline(always)] + pub fn empty<'a>() -> &'a List { + #[repr(align(64))] + struct MaxAlign; + + assert!(mem::align_of::() <= mem::align_of::()); + + #[repr(C)] + struct InOrder(T, U); + + // The empty slice is static and contains a single `0` usize (for the + // length) that is 64-byte aligned, thus featuring the necessary + // trailing padding for elements with up to 64-byte alignment. + static EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); + unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } + } +} impl List { + /// Allocates a list from `arena` and copies the contents of `slice` into it. + /// + /// WARNING: the contents *must be unique*, such that no list with these + /// contents has been previously created. If not, operations such as `eq` + /// and `hash` might give incorrect results. + /// + /// Panics if `T` is `Drop`, or `T` is zero-sized, or the slice is empty + /// (because the empty list exists statically, and is available via + /// `empty()`). #[inline] pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { assert!(!mem::needs_drop::()); @@ -73,7 +91,7 @@ .cast::() .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); - &mut *mem + &*mem } } @@ -107,11 +125,24 @@ } } +impl PartialEq for List { + #[inline] + fn eq(&self, other: &List) -> bool { + // Pointer equality implies list equality (due to the unique contents + // assumption). + ptr::eq(self, other) + } +} + +impl Eq for List {} + impl Ord for List where T: Ord, { fn cmp(&self, other: &List) -> Ordering { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } } } @@ -121,6 +152,8 @@ T: PartialOrd, { fn partial_cmp(&self, other: &List) -> Option { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Some(Ordering::Equal) } else { @@ -129,17 +162,11 @@ } } -impl PartialEq for List { - #[inline] - fn eq(&self, other: &List) -> bool { - ptr::eq(self, other) - } -} -impl Eq for List {} - impl Hash for List { #[inline] fn hash(&self, s: &mut H) { + // Pointer hashing is sufficient (due to the unique contents + // assumption). (self as *const List).hash(s) } } @@ -168,13 +195,24 @@ } } -impl List { - #[inline(always)] - pub fn empty<'a>() -> &'a List { - #[repr(align(64), C)] - struct EmptySlice([u8; 64]); - static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); - assert!(mem::align_of::() <= 64); - unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } +unsafe impl Sync for List {} + +unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { + const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; + + #[inline] + fn into_usize(self) -> usize { + self as *const List as usize + } + + #[inline] + unsafe fn from_usize(ptr: usize) -> &'a List { + &*(ptr as *const List) + } + + unsafe fn with_ref R>(ptr: usize, f: F) -> R { + // `Self` is `&'a List` which impls `Copy`, so this is fine. + let ptr = Self::from_usize(ptr); + f(&ptr) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/_match.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/_match.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/_match.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/_match.rs 2022-02-23 04:07:21.000000000 +0000 @@ -23,13 +23,13 @@ param_env: ty::ParamEnv<'tcx>, } -impl Match<'tcx> { +impl<'tcx> Match<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> { Match { tcx, param_env } } } -impl TypeRelation<'tcx> for Match<'tcx> { +impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { fn tag(&self) -> &'static str { "Match" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html -pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; @@ -77,7 +77,7 @@ GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, - UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind, + UpvarSubsts, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; @@ -230,6 +230,19 @@ ConstIfConst, } +impl BoundConstness { + /// Reduce `self` and `constness` to two possible combined states instead of four. + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { + match (constness, self) { + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, + (_, this) => { + *this = BoundConstness::NotConst; + hir::Constness::NotConst + } + } + } +} + impl fmt::Display for BoundConstness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -721,6 +734,15 @@ pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { + pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) { + if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { + // remap without changing constness of this predicate. + // this is because `T: ~const Drop` has a different meaning to `T: Drop` + param_env.remap_constness_with(self.constness) + } else { + *param_env = param_env.with_constness(self.constness.and(param_env.constness())) + } + } pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -839,27 +861,13 @@ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } -impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) } } -impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.value - .map_bound(|trait_ref| { - PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: self.constness, - polarity: ty::ImplPolarity::Positive, - }) - }) - .to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Trait).to_predicate(tcx) @@ -885,12 +893,10 @@ } impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_ref(self) -> Option>> { + pub fn to_opt_poly_trait_pred(self) -> Option> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Trait(t) => { - Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) }) - } + PredicateKind::Trait(t) => Some(predicate.rebind(t)), PredicateKind::Projection(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) @@ -1221,23 +1227,33 @@ /// want `Reveal::All`. /// /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List>, traits::Reveal, true>, + packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, } -unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal { - const BITS: usize = 1; +#[derive(Copy, Clone)] +struct ParamTag { + reveal: traits::Reveal, + constness: hir::Constness, +} + +unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { + const BITS: usize = 2; #[inline] fn into_usize(self) -> usize { match self { - traits::Reveal::UserFacing => 0, - traits::Reveal::All => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, + Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, + Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, } } #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => traits::Reveal::UserFacing, - 1 => traits::Reveal::All, + 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, _ => std::hint::unreachable_unchecked(), } } @@ -1248,6 +1264,7 @@ f.debug_struct("ParamEnv") .field("caller_bounds", &self.caller_bounds()) .field("reveal", &self.reveal()) + .field("constness", &self.constness()) .finish() } } @@ -1256,17 +1273,26 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.caller_bounds().hash_stable(hcx, hasher); self.reveal().hash_stable(hcx, hasher); + self.constness().hash_stable(hcx, hasher); } } impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ParamEnv::new( + self.caller_bounds().try_fold_with(folder)?, + self.reveal().try_fold_with(folder)?, + self.constness().try_fold_with(folder)?, + )) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor) + self.reveal().visit_with(visitor)?; + self.constness().visit_with(visitor) } } @@ -1277,7 +1303,7 @@ /// type-checking. #[inline] pub fn empty() -> Self { - Self::new(List::empty(), Reveal::UserFacing) + Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) } #[inline] @@ -1287,7 +1313,12 @@ #[inline] pub fn reveal(self) -> traits::Reveal { - self.packed.tag() + self.packed.tag().reveal + } + + #[inline] + pub fn constness(self) -> hir::Constness { + self.packed.tag().constness } /// Construct a trait environment with no where-clauses in scope @@ -1299,20 +1330,47 @@ /// or invoke `param_env.with_reveal_all()`. #[inline] pub fn reveal_all() -> Self { - Self::new(List::empty(), Reveal::All) + Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) } /// Construct a trait environment with the given set of predicates. #[inline] - pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) } + pub fn new( + caller_bounds: &'tcx List>, + reveal: Reveal, + constness: hir::Constness, + ) -> Self { + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } } pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(Reveal::UserFacing); + self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); self } + #[inline] + pub fn with_constness(mut self, constness: hir::Constness) -> Self { + self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); + self + } + + #[inline] + pub fn with_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); + self + } + + #[inline] + pub fn without_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); + self + } + + #[inline] + pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { + *self = self.with_constness(constness.and(self.constness())) + } + /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is @@ -1323,17 +1381,21 @@ /// will be normalized to their underlying types. /// See PR #65989 and issue #65918 for more details pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed.tag() == traits::Reveal::All { + if self.packed.tag().reveal == traits::Reveal::All { return self; } - ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All) + ParamEnv::new( + tcx.normalize_opaque_types(self.caller_bounds()), + Reveal::All, + self.constness(), + ) } /// Returns this same environment but with no caller bounds. #[inline] pub fn without_caller_bounds(self) -> Self { - Self::new(List::empty(), self.reveal()) + Self::new(List::empty(), self.reveal(), self.constness()) } /// Creates a suitable environment in which to perform trait @@ -1363,33 +1425,23 @@ } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] -pub struct ConstnessAnd { - pub constness: BoundConstness, - pub value: T, -} - // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that // the constness of trait bounds is being propagated correctly. -pub trait WithConstness: Sized { - #[inline] - fn with_constness(self, constness: BoundConstness) -> ConstnessAnd { - ConstnessAnd { constness, value: self } - } - +impl<'tcx> PolyTraitRef<'tcx> { #[inline] - fn with_const_if_const(self) -> ConstnessAnd { - self.with_constness(BoundConstness::ConstIfConst) + pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| ty::TraitPredicate { + trait_ref, + constness, + polarity: ty::ImplPolarity::Positive, + }) } - #[inline] - fn without_const(self) -> ConstnessAnd { + pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) } } -impl WithConstness for T {} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, @@ -1400,6 +1452,12 @@ pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { (self.param_env, self.value) } + + #[inline] + pub fn without_const(mut self) -> Self { + self.param_env = self.param_env.without_const(); + self + } } impl<'a, 'tcx, T> HashStable> for ParamEnvAnd<'tcx, T> @@ -1423,7 +1481,7 @@ } bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct VariantFlags: u32 { const NO_VARIANT_FLAGS = 0; /// Indicates whether the field list of this variant is `#[non_exhaustive]`. @@ -1435,7 +1493,7 @@ } /// Definition of a variant -- a struct's fields or an enum variant. -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct VariantDef { /// `DefId` that identifies the variant itself. /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. @@ -1537,7 +1595,7 @@ Relative(u32), } -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct FieldDef { pub did: DefId, #[stable_hasher(project(name))] @@ -1559,9 +1617,9 @@ // the seed stored in `ReprOptions.layout_seed` const RANDOMIZE_LAYOUT = 1 << 5; // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | - ReprFlags::IS_SIMD.bits | - ReprFlags::IS_LINEAR.bits; + const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits + | ReprFlags::IS_SIMD.bits + | ReprFlags::IS_LINEAR.bits; } } @@ -1591,7 +1649,14 @@ // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + + // If the user defined a custom seed for layout randomization, xor the item's + // path hash with the user defined seed, this will allowing determinism while + // still allowing users to further randomize layout generation for e.g. fuzzing + if let Some(user_seed) = tcx.sess.opts.debugging_opts.layout_seed { + field_shuffle_seed ^= user_seed; + } for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { @@ -1705,7 +1770,7 @@ impl<'tcx> FieldDef { /// Returns the type of this field. The resulting type is not normalized. The `subst` is - /// typically obtained via the second field of `TyKind::AdtDef`. + /// typically obtained via the second field of [`TyKind::Adt`]. pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { tcx.type_of(self.did).subst(tcx, subst) } @@ -2049,13 +2114,17 @@ } } -/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return opaque_ty.impl_trait_fn; - } +/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. +pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let def_id = def_id.as_local()?; + if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { + return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { + Some(parent) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; } } None diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,10 +8,28 @@ //! or constant found within. (This underlying query is what is cached.) use crate::mir; -use crate::ty::fold::{TypeFoldable, TypeFolder}; +use crate::traits::query::NoSolution; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; +#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] +pub enum NormalizationError<'tcx> { + Type(Ty<'tcx>), + Const(ty::Const<'tcx>), + ConstantKind(mir::ConstantKind<'tcx>), +} + +impl<'tcx> NormalizationError<'tcx> { + pub fn get_type_for_failure(&self) -> String { + match self { + NormalizationError::Type(t) => format!("{}", t), + NormalizationError::Const(c) => format!("{}", c), + NormalizationError::ConstantKind(ck) => format!("{}", ck), + } + } +} + impl<'tcx> TyCtxt<'tcx> { /// Erase the regions in `value` and then fully normalize all the /// types found within. The result will also have regions erased. @@ -32,6 +50,8 @@ // Erase first before we do the real query -- this keeps the // cache from being too polluted. let value = self.erase_regions(value); + debug!(?value); + if !value.has_projections() { value } else { @@ -39,6 +59,39 @@ } } + /// Tries to erase the regions in `value` and then fully normalize all the + /// types found within. The result will also have regions erased. + /// + /// Contrary to `normalize_erasing_regions` this function does not assume that normalization + /// succeeds. + pub fn try_normalize_erasing_regions( + self, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> + where + T: TypeFoldable<'tcx>, + { + debug!( + "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + std::any::type_name::(), + value, + param_env, + ); + + // Erase first before we do the real query -- this keeps the + // cache from being too polluted. + let value = self.erase_regions(value); + debug!(?value); + + if !value.has_projections() { + Ok(value) + } else { + let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env); + value.try_fold_with(&mut folder) + } + } + /// If you have a `Binder<'tcx, T>`, you can do this to strip out the /// late-bound regions and then normalize the result, yielding up /// a `T` (with regions erased). This is appropriate when the @@ -62,6 +115,8 @@ /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then normalizing any associated /// types. + /// Panics if normalization fails. In case normalization might fail + /// use `try_subst_and_normalize_erasing_regions` instead. pub fn subst_and_normalize_erasing_regions( self, param_substs: SubstsRef<'tcx>, @@ -81,6 +136,30 @@ let substituted = value.subst(self, param_substs); self.normalize_erasing_regions(param_env, substituted) } + + /// Monomorphizes a type from the AST by first applying the + /// in-scope substitutions and then trying to normalize any associated + /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// not assume that normalization succeeds. + pub fn try_subst_and_normalize_erasing_regions( + self, + param_substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> + where + T: TypeFoldable<'tcx>, + { + debug!( + "subst_and_normalize_erasing_regions(\ + param_substs={:?}, \ + value={:?}, \ + param_env={:?})", + param_substs, value, param_env, + ); + let substituted = value.subst(self, param_substs); + self.try_normalize_erasing_regions(param_env, substituted) + } } struct NormalizeAfterErasingRegionsFolder<'tcx> { @@ -89,16 +168,22 @@ } impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { + #[instrument(skip(self), level = "debug")] fn normalize_generic_arg_after_erasing_regions( &self, arg: ty::GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { let arg = self.param_env.and(arg); - self.tcx.normalize_generic_arg_after_erasing_regions(arg) + debug!(?arg); + + self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( + "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", + arg.value + )) } } -impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { +impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -115,6 +200,69 @@ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { // FIXME: This *probably* needs canonicalization too! let arg = self.param_env.and(c); - self.tcx.normalize_mir_const_after_erasing_regions(arg) + self.tcx + .try_normalize_mir_const_after_erasing_regions(arg) + .unwrap_or_else(|_| bug!("failed to normalize {:?}", c)) + } +} + +struct TryNormalizeAfterErasingRegionsFolder<'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + TryNormalizeAfterErasingRegionsFolder { tcx, param_env } + } + + #[instrument(skip(self), level = "debug")] + fn try_normalize_generic_arg_after_erasing_regions( + &self, + arg: ty::GenericArg<'tcx>, + ) -> Result, NoSolution> { + let arg = self.param_env.and(arg); + debug!(?arg); + + self.tcx.try_normalize_generic_arg_after_erasing_regions(arg) + } +} + +impl<'tcx> TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { + type Error = NormalizationError<'tcx>; + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } +} + +impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { + match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) { + Ok(t) => Ok(t.expect_ty()), + Err(_) => Err(NormalizationError::Type(ty)), + } + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + match self.try_normalize_generic_arg_after_erasing_regions(c.into()) { + Ok(t) => Ok(t.expect_const()), + Err(_) => Err(NormalizationError::Const(*c)), + } + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + // FIXME: This *probably* needs canonicalization too! + let arg = self.param_env.and(c); + match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) { + Ok(c) => Ok(c), + Err(_) => Err(NormalizationError::ConstantKind(c)), + } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -37,7 +37,7 @@ type DynExistential; type Const; - fn tcx(&'a self) -> TyCtxt<'tcx>; + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn print_def_path( self, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/pretty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/pretty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/pretty.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/print/pretty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -303,7 +303,7 @@ match self.tcx().trimmed_def_paths(()).get(&def_id) { None => Ok((self, false)), Some(symbol) => { - self.write_str(&symbol.as_str())?; + self.write_str(symbol.as_str())?; Ok((self, true)) } } @@ -319,6 +319,9 @@ /// /// `callers` is a chain of visible_parent's leading to `def_id`, /// to support cycle detection during recursion. + /// + /// This method returns false if we can't print the visible path, so + /// `print_def_path` can fall back on the item's real definition path. fn try_print_visible_def_path_recur( mut self, def_id: DefId, @@ -405,19 +408,7 @@ Some(parent) => parent, None => return Ok((self, false)), }; - if callers.contains(&visible_parent) { - return Ok((self, false)); - } - callers.push(visible_parent); - // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid - // knowing ahead of time whether the entire path will succeed or not. - // To support printers that do not implement `PrettyPrinter`, a `Vec` or - // linked list on the stack would need to be built, before any printing. - match self.try_print_visible_def_path_recur(visible_parent, callers)? { - (cx, false) => return Ok((cx, false)), - (cx, true) => self = cx, - } - callers.pop(); + let actual_parent = self.tcx().parent(def_id); debug!( "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", @@ -463,14 +454,21 @@ // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { + // Item might be re-exported several times, but filter for the one + // that's public and whose identifier isn't `_`. let reexport = self .tcx() .item_children(visible_parent) .iter() - .find(|child| child.res.opt_def_id() == Some(def_id)) + .filter(|child| child.res.opt_def_id() == Some(def_id)) + .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) .map(|child| child.ident.name); - if let Some(reexport) = reexport { - *name = reexport; + + if let Some(new_name) = reexport { + *name = new_name; + } else { + // There is no name that is public and isn't `_`, so bail. + return Ok((self, false)); } } // Re-exported `extern crate` (#43189). @@ -481,6 +479,20 @@ } debug!("try_print_visible_def_path: data={:?}", data); + if callers.contains(&visible_parent) { + return Ok((self, false)); + } + callers.push(visible_parent); + // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid + // knowing ahead of time whether the entire path will succeed or not. + // To support printers that do not implement `PrettyPrinter`, a `Vec` or + // linked list on the stack would need to be built, before any printing. + match self.try_print_visible_def_path_recur(visible_parent, callers)? { + (cx, false) => return Ok((cx, false)), + (cx, true) => self = cx, + } + callers.pop(); + Ok((self.path_append(Ok, &DisambiguatedDefPathData { data, disambiguator: 0 })?, true)) } @@ -1513,7 +1525,7 @@ pub name_resolver: Option Option>>, } -impl Deref for FmtPrinter<'a, 'tcx, F> { +impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> { type Target = FmtPrinterData<'a, 'tcx, F>; fn deref(&self) -> &Self::Target { &self.0 @@ -1526,7 +1538,7 @@ } } -impl FmtPrinter<'a, 'tcx, F> { +impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> { pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self { FmtPrinter(Box::new(FmtPrinterData { tcx, @@ -1563,7 +1575,7 @@ } } -impl TyCtxt<'t> { +impl<'t> TyCtxt<'t> { /// Returns a string identifying this `DefId`. This string is /// suitable for user output. pub fn def_path_str(self, def_id: DefId) -> String { @@ -1585,7 +1597,7 @@ } } -impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { type Error = fmt::Error; type Path = Self; @@ -1594,7 +1606,7 @@ type DynExistential = Self; type Const = Self; - fn tcx(&'a self) -> TyCtxt<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -1740,30 +1752,26 @@ ) -> Result { self = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(self); } - // FIXME(eddyb) `name` should never be empty, but it - // currently is for `extern { ... }` "foreign modules". let name = disambiguated_data.data.name(); - if name != DefPathDataName::Named(kw::Empty) { - if !self.empty_path { - write!(self, "::")?; - } + if !self.empty_path { + write!(self, "::")?; + } - if let DefPathDataName::Named(name) = name { - if Ident::with_dummy_span(name).is_raw_guess() { - write!(self, "r#")?; - } + if let DefPathDataName::Named(name) = name { + if Ident::with_dummy_span(name).is_raw_guess() { + write!(self, "r#")?; } + } - let verbose = self.tcx.sess.verbose(); - disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; + let verbose = self.tcx.sess.verbose(); + disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; - self.empty_path = false; - } + self.empty_path = false; Ok(self) } @@ -1796,7 +1804,7 @@ } } -impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { fn infer_ty_name(&self, id: ty::TyVid) -> Option { self.0.name_resolver.as_ref().and_then(|func| func(id)) } @@ -2062,7 +2070,7 @@ // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. -impl FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, value: &ty::Binder<'tcx, T>, @@ -2316,7 +2324,8 @@ macro_rules! forward_display_to_print { ($($ty:ty),+) => { - $(impl fmt::Display for $ty { + // Some of the $ty arguments may not actually use 'tcx + $(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { tcx.lift(*self) @@ -2364,7 +2373,7 @@ #[derive(Copy, Clone, TypeFoldable, Lift)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); -impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { +impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } @@ -2376,13 +2385,13 @@ #[derive(Copy, Clone, TypeFoldable, Lift)] pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>); -impl fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { +impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } -impl ty::TraitRef<'tcx> { +impl<'tcx> ty::TraitRef<'tcx> { pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { TraitRefPrintOnlyTraitPath(self) } @@ -2392,7 +2401,7 @@ } } -impl ty::Binder<'tcx, ty::TraitRef<'tcx>> { +impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/query.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/query.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/query.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/query.rs 2022-02-23 04:07:21.000000000 +0000 @@ -28,6 +28,7 @@ }; use crate::traits::specialization_graph; use crate::traits::{self, ImplSource}; +use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; @@ -69,7 +70,7 @@ pub span: Span, } -impl Deref for TyCtxtAt<'tcx> { +impl<'tcx> Deref for TyCtxtAt<'tcx> { type Target = TyCtxt<'tcx>; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -82,7 +83,7 @@ pub tcx: TyCtxt<'tcx>, } -impl TyCtxt<'tcx> { +impl<'tcx> TyCtxt<'tcx> { /// Returns a transparent wrapper for `TyCtxt`, which ensures queries /// are executed instead of just returning their results. #[inline(always)] @@ -156,6 +157,16 @@ }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -197,11 +208,13 @@ $($(#[$attr])* pub $name: QueryCacheStore>,)* } - impl TyCtxtEnsure<$tcx> { + impl<$tcx> TyCtxtEnsure<$tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); let lookup = match cached { @@ -213,7 +226,7 @@ })* } - impl TyCtxt<$tcx> { + impl<$tcx> TyCtxt<$tcx> { $($(#[$attr])* #[inline(always)] #[must_use] @@ -223,12 +236,14 @@ })* } - impl TyCtxtAt<$tcx> { + impl<$tcx> TyCtxtAt<$tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx> { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone); let lookup = match cached { @@ -343,7 +358,7 @@ use sealed::IntoQueryParam; -impl TyCtxt<'tcx> { +impl<'tcx> TyCtxt<'tcx> { pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { let def_id = def_id.into_query_param(); self.opt_def_kind(def_id) @@ -351,7 +366,7 @@ } } -impl TyCtxtAt<'tcx> { +impl<'tcx> TyCtxtAt<'tcx> { pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { let def_id = def_id.into_query_param(); self.opt_def_kind(def_id) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/relate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/relate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/relate.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/relate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; +use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; @@ -59,8 +59,9 @@ item_def_id, a_subst, b_subst ); - let opt_variances = self.tcx().variances_of(item_def_id); - relate_substs(self, Some(opt_variances), a_subst, b_subst) + let tcx = self.tcx(); + let opt_variances = tcx.variances_of(item_def_id); + relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -116,7 +117,7 @@ relation: &mut R, a: ty::TypeAndMut<'tcx>, b: ty::TypeAndMut<'tcx>, - kind: ty::VarianceDiagMutKind, + base_ty: Ty<'tcx>, ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> { debug!("{}.mts({:?}, {:?})", relation.tag(), a, b); if a.mutbl != b.mutbl { @@ -125,24 +126,40 @@ let mutbl = a.mutbl; let (variance, info) = match mutbl { ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None), - ast::Mutability::Mut => (ty::Invariant, ty::VarianceDiagInfo::Mut { kind, ty: a.ty }), + ast::Mutability::Mut => { + (ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 }) + } }; let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) } } -pub fn relate_substs>( +pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - variances: Option<&[ty::Variance]>, + variances: Option<(DefId, &[ty::Variance])>, a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); + let mut cached_ty = None; let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { - let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, ty::VarianceDiagInfo::default(), a, b) + let (variance, variance_info) = match variances { + Some((ty_def_id, variances)) => { + let variance = variances[i]; + let variance_info = if variance == ty::Invariant { + let ty = + cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); + ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } + } else { + ty::VarianceDiagInfo::default() + }; + (variance, variance_info) + } + None => (ty::Invariant, ty::VarianceDiagInfo::default()), + }; + relation.relate_with_variance(variance, variance_info, a, b) }); tcx.mk_substs(params) @@ -218,19 +235,6 @@ } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::ConstnessAnd { - fn relate>( - relation: &mut R, - a: ty::ConstnessAnd, - b: ty::ConstnessAnd, - ) -> RelateResult<'tcx, ty::ConstnessAnd> { - Ok(ty::ConstnessAnd { - constness: relation.relate(a.constness, b.constness)?, - value: relation.relate(a.value, b.value)?, - }) - } -} - impl<'tcx> Relate<'tcx> for ast::Unsafety { fn relate>( relation: &mut R, @@ -366,7 +370,7 @@ /// The main "type relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. -pub fn super_relate_tys>( +pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, @@ -449,7 +453,7 @@ } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { - let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::RawPtr)?; + let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(tcx.mk_ptr(mt)) } @@ -462,7 +466,7 @@ )?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; - let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::Ref)?; + let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(tcx.mk_ref(r, mt)) } @@ -539,7 +543,7 @@ /// The main "const relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. -pub fn super_relate_consts>( +pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, @@ -612,7 +616,7 @@ if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } -fn check_const_value_eq>( +fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a_val: ConstValue<'tcx>, b_val: ConstValue<'tcx>, @@ -845,17 +849,9 @@ /////////////////////////////////////////////////////////////////////////// // Error handling -pub fn expected_found(relation: &mut R, a: T, b: T) -> ExpectedFound +pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound where R: TypeRelation<'tcx>, { - expected_found_bool(relation.a_is_expected(), a, b) -} - -pub fn expected_found_bool(a_is_expected: bool, a: T, b: T) -> ExpectedFound { - if a_is_expected { - ExpectedFound { expected: a, found: b } - } else { - ExpectedFound { expected: b, found: a } - } + ExpectedFound::new(relation.a_is_expected(), a, b) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/structural_impls.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/structural_impls.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/structural_impls.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/structural_impls.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,7 @@ use crate::mir::interpret; use crate::mir::ProjectionKind; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; @@ -13,6 +13,7 @@ use rustc_index::vec::{Idx, IndexVec}; use std::fmt; +use std::mem::ManuallyDrop; use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; @@ -46,19 +47,19 @@ } } -impl fmt::Debug for ty::UpvarBorrow<'tcx> { +impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "UpvarBorrow({:?}, {:?})", self.kind, self.region) } } -impl fmt::Debug for ty::ExistentialTraitRef<'tcx> { +impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } } -impl fmt::Debug for ty::adjustment::Adjustment<'tcx> { +impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?} -> {}", self.kind, self.target) } @@ -110,7 +111,7 @@ } } -impl fmt::Debug for ty::FnSig<'tcx> { +impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output()) } @@ -128,13 +129,13 @@ } } -impl fmt::Debug for ty::TraitRef<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } } -impl fmt::Debug for Ty<'tcx> { +impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } @@ -152,7 +153,7 @@ } } -impl fmt::Debug for ty::TraitPredicate<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let ty::BoundConstness::ConstIfConst = self.constness { write!(f, "~const ")?; @@ -161,19 +162,19 @@ } } -impl fmt::Debug for ty::ProjectionPredicate<'tcx> { +impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty) } } -impl fmt::Debug for ty::Predicate<'tcx> { +impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.kind()) } } -impl fmt::Debug for ty::PredicateKind<'tcx> { +impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { ty::PredicateKind::Trait(ref a) => a.fmt(f), @@ -480,7 +481,7 @@ type Lifted = ty::ParamEnv<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) + .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness())) } } @@ -669,8 +670,11 @@ /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -679,8 +683,11 @@ } impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { - fn super_fold_with>(self, folder: &mut F) -> (T, U) { - (self.0.fold_with(folder), self.1.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result<(T, U), F::Error> { + Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -692,8 +699,15 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (A, B, C) { - fn super_fold_with>(self, folder: &mut F) -> (A, B, C) { - (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result<(A, B, C), F::Error> { + Ok(( + self.0.try_fold_with(folder)?, + self.1.try_fold_with(folder)?, + self.2.try_fold_with(folder)?, + )) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -718,9 +732,42 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { - fn super_fold_with>(self, folder: &mut F) -> Self { - // FIXME: Reuse the `Rc` here. - Rc::new((*self).clone().fold_with(folder)) + fn try_super_fold_with>( + mut self, + folder: &mut F, + ) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Rc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Rc::make_mut` will accomplish (by + // allocating a new `Rc` and cloning the `T` only if required). + // This is done *before* casting to `Rc>` so that + // panicking during `make_mut` does not leak the `T`. + Rc::make_mut(&mut self); + + // Casting to `Rc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Rc::into_raw(self).cast::>(); + let mut unique = Rc::from_raw(ptr); + + // Call to `Rc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Rc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = ManuallyDrop::new(folded); + + // Cast back to `Rc`. + Ok(Rc::from_raw(Rc::into_raw(unique).cast())) + } } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -729,9 +776,42 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc { - fn super_fold_with>(self, folder: &mut F) -> Self { - // FIXME: Reuse the `Arc` here. - Arc::new((*self).clone().fold_with(folder)) + fn try_super_fold_with>( + mut self, + folder: &mut F, + ) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Arc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Arc::make_mut` will accomplish (by + // allocating a new `Arc` and cloning the `T` only if required). + // This is done *before* casting to `Arc>` so that + // panicking during `make_mut` does not leak the `T`. + Arc::make_mut(&mut self); + + // Casting to `Arc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Arc::into_raw(self).cast::>(); + let mut unique = Arc::from_raw(ptr); + + // Call to `Arc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Arc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = ManuallyDrop::new(folded); + + // Cast back to `Arc`. + Ok(Arc::from_raw(Arc::into_raw(unique).cast())) + } } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -740,8 +820,11 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|value| value.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|value| value.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -750,8 +833,11 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|t| t.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -760,8 +846,11 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|t| t.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -770,12 +859,15 @@ } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_bound(|ty| ty.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_bound(|ty| ty.try_fold_with(folder)) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_binder(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_binder(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -788,7 +880,10 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } @@ -798,7 +893,10 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) } @@ -808,7 +906,10 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } @@ -818,24 +919,33 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::ty::InstanceDef::*; - Self { - substs: self.substs.fold_with(folder), + Ok(Self { + substs: self.substs.try_fold_with(folder)?, def: match self.def { - Item(def) => Item(def.fold_with(folder)), - VtableShim(did) => VtableShim(did.fold_with(folder)), - ReifyShim(did) => ReifyShim(did.fold_with(folder)), - Intrinsic(did) => Intrinsic(did.fold_with(folder)), - FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)), - Virtual(did, i) => Virtual(did.fold_with(folder), i), + Item(def) => Item(def.try_fold_with(folder)?), + VtableShim(did) => VtableShim(did.try_fold_with(folder)?), + ReifyShim(did) => ReifyShim(did.try_fold_with(folder)?), + Intrinsic(did) => Intrinsic(did.try_fold_with(folder)?), + FnPtrShim(did, ty) => { + FnPtrShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + Virtual(did, i) => Virtual(did.try_fold_with(folder)?, i), ClosureOnceShim { call_once, track_caller } => { - ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller } + ClosureOnceShim { call_once: call_once.try_fold_with(folder)?, track_caller } + } + DropGlue(did, ty) => { + DropGlue(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + CloneShim(did, ty) => { + CloneShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) } - DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)), - CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)), }, - } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -860,8 +970,11 @@ } impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Self { instance: self.instance.fold_with(folder), promoted: self.promoted } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Self { instance: self.instance.try_fold_with(folder)?, promoted: self.promoted }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -870,26 +983,31 @@ } impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { let kind = match *self.kind() { - ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), - ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), - ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), - ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)), + ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?), + ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), + ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), + ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)) + ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) + } + ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), + ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), + ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), + ty::Ref(r, ty, mutbl) => { + ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } - ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), - ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)), - ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), - ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), ty::Generator(did, substs, movability) => { - ty::Generator(did, substs.fold_with(folder), movability) + ty::Generator(did, substs.try_fold_with(folder)?, movability) } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), - ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), - ty::Projection(data) => ty::Projection(data.fold_with(folder)), - ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), + ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), + ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), + ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), + ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), ty::Bool | ty::Char @@ -903,14 +1021,14 @@ | ty::Bound(..) | ty::Placeholder(..) | ty::Never - | ty::Foreign(..) => return self, + | ty::Foreign(..) => return Ok(self), }; - if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) } + Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_ty(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_ty(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -961,12 +1079,15 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_region(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_region(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -979,13 +1100,16 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_predicate(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_predicate(self) } - fn super_fold_with>(self, folder: &mut F) -> Self { - let new = self.inner.kind.fold_with(folder); - folder.tcx().reuse_or_mk_predicate(self, new) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let new = self.inner.kind.try_fold_with(folder)?; + Ok(folder.tcx().reuse_or_mk_predicate(self, new)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1006,7 +1130,10 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v)) } @@ -1016,8 +1143,11 @@ } impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|x| x.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|x| x.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1026,18 +1156,21 @@ } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - let ty = self.ty.fold_with(folder); - let val = self.val.fold_with(folder); + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let ty = self.ty.try_fold_with(folder)?; + let val = self.val.try_fold_with(folder)?; if ty != self.ty || val != self.val { - folder.tcx().mk_const(ty::Const { ty, val }) + Ok(folder.tcx().mk_const(ty::Const { ty, val })) } else { - self + Ok(self) } } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_const(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_const(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1051,16 +1184,19 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - match self { - ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), - ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)), + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(match self { + ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?), + ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?), + ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) | ty::ConstKind::Error(_) => self, - } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1077,8 +1213,11 @@ } impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -1087,12 +1226,15 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1112,12 +1254,15 @@ } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with>(&self, visitor: &mut V) -> ControlFlow { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/sty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/sty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/sty.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/sty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,9 +8,7 @@ use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; -use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, -}; +use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; @@ -200,7 +198,7 @@ Error(DelaySpanBugEmitted), } -impl TyKind<'tcx> { +impl<'tcx> TyKind<'tcx> { #[inline] pub fn is_primitive(&self) -> bool { matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_)) @@ -356,14 +354,17 @@ /// The ordering assumed here must match that used by `ClosureSubsts::new` above. fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> { match self.substs[..] { - [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { - ClosureSubstsParts { - parent_substs, - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, - } - } + [ + ref parent_substs @ .., + closure_kind_ty, + closure_sig_as_fn_ptr_ty, + tupled_upvars_ty, + ] => ClosureSubstsParts { + parent_substs, + closure_kind_ty, + closure_sig_as_fn_ptr_ty, + tupled_upvars_ty, + }, _ => bug!("closure substs missing synthetics"), } } @@ -786,7 +787,7 @@ tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)) } (AutoTrait(ref a), AutoTrait(ref b)) => { - tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash) + tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) } (Trait(_), _) => Ordering::Less, (Projection(_), Trait(_)) => Ordering::Greater, @@ -1101,6 +1102,18 @@ Binder(value, self.1) } + pub fn try_map_bound, E>(self, f: F) -> Result, E> + where + F: FnOnce(T) -> Result, + { + let value = f(self.0)?; + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Ok(Binder(value, self.1)) + } + /// Wraps a `value` in a binder, using the same bound variables as the /// current `Binder`. This should not be used if the new value *changes* /// the bound variables. Note: the (old or new) value itself does not @@ -2269,36 +2282,26 @@ /// We will not add any additional information to error messages. #[default] None, - /// We switched our variance because a type occurs inside - /// the generic argument of a mutable reference or pointer - /// (`*mut T` or `&mut T`). In either case, our variance - /// will always be `Invariant`. - Mut { - /// Tracks whether we had a mutable pointer or reference, - /// for better error messages - kind: VarianceDiagMutKind, - /// The type parameter of the mutable pointer/reference - /// (the `T` in `&mut T` or `*mut T`). + /// We switched our variance because a generic argument occurs inside + /// the invariant generic argument of another type. + Invariant { + /// The generic type containing the generic parameter + /// that changes the variance (e.g. `*mut T`, `MyStruct`) ty: Ty<'tcx>, + /// The index of the generic parameter being used + /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) + param_index: u32, }, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum VarianceDiagMutKind { - /// A mutable raw pointer (`*mut T`) - RawPtr, - /// A mutable reference (`&mut T`) - Ref, -} - impl<'tcx> VarianceDiagInfo<'tcx> { /// Mirrors `Variance::xform` - used to 'combine' the existing /// and new `VarianceDiagInfo`s when our variance changes. pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> { - // For now, just use the first `VarianceDiagInfo::Mut` that we see + // For now, just use the first `VarianceDiagInfo::Invariant` that we see match self { VarianceDiagInfo::None => other, - VarianceDiagInfo::Mut { .. } => self, + VarianceDiagInfo::Invariant { .. } => self, } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/subst.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/subst.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/subst.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/subst.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; @@ -67,7 +67,7 @@ } } -impl fmt::Debug for GenericArg<'tcx> { +impl<'tcx> fmt::Debug for GenericArg<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.fmt(f), @@ -153,11 +153,14 @@ } impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), - GenericArgKind::Type(ty) => ty.fold_with(folder).into(), - GenericArgKind::Const(ct) => ct.fold_with(folder).into(), + GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), + GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), + GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), } } @@ -372,7 +375,10 @@ } impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. // The match arms are in order of frequency. The 1, 2, and 0 cases are @@ -381,22 +387,27 @@ // calling `intern_substs`. match self.len() { 1 => { - let param0 = self[0].fold_with(folder); - if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) } + let param0 = self[0].try_fold_with(folder)?; + if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) } } 2 => { - let param0 = self[0].fold_with(folder); - let param1 = self[1].fold_with(folder); + let param0 = self[0].try_fold_with(folder)?; + let param1 = self[1].try_fold_with(folder)?; if param0 == self[0] && param1 == self[1] { - self + Ok(self) } else { - folder.tcx().intern_substs(&[param0, param1]) + Ok(folder.tcx().intern_substs(&[param0, param1])) } } - 0 => self, + 0 => Ok(self), _ => { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); - if params[..] == self[..] { self } else { folder.tcx().intern_substs(¶ms) } + let params: SmallVec<[_; 8]> = + self.iter().map(|k| k.try_fold_with(folder)).collect::>()?; + if params[..] == self[..] { + Ok(self) + } else { + Ok(folder.tcx().intern_substs(¶ms)) + } } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/trait_def.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/trait_def.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/trait_def.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/trait_def.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject; +use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; @@ -68,7 +68,7 @@ pub struct TraitImpls { blanket_impls: Vec, /// Impls indexed by their simplified self type, for fast lookup. - non_blanket_impls: FxIndexMap>, + non_blanket_impls: FxIndexMap>, } impl TraitImpls { @@ -146,6 +146,11 @@ self_ty: Ty<'tcx>, mut f: F, ) -> Option { + // FIXME: This depends on the set of all impls for the trait. That is + // unfortunate wrt. incremental compilation. + // + // If we want to be faster, we could have separate queries for + // blanket and non-blanket impls, and compare them separately. let impls = self.trait_impls_of(def_id); for &impl_def_id in impls.blanket_impls.iter() { @@ -154,32 +159,16 @@ } } - // simplify_type(.., false) basically replaces type parameters and - // projections with infer-variables. This is, of course, done on - // the impl trait-ref when it is instantiated, but not on the - // predicate trait-ref which is passed here. - // - // for example, if we match `S: Copy` against an impl like - // `impl Copy for Option`, we replace the type variable - // in `Option` with an infer variable, to `Option<_>` (this - // doesn't actually change fast_reject output), but we don't - // replace `S` with anything - this impl of course can't be - // selected, and as there are hundreds of similar impls, - // considering them would significantly harm performance. - - // This depends on the set of all impls for the trait. That is - // unfortunate. When we get red-green recompilation, we would like - // to have a way of knowing whether the set of relevant impls - // changed. The most naive - // way would be to compute the Vec of relevant impls and see whether - // it differs between compilations. That shouldn't be too slow by - // itself - we do quite a bit of work for each relevant impl anyway. - // - // If we want to be faster, we could have separate queries for - // blanket and non-blanket impls, and compare them separately. + // Note that we're using `SimplifyParams::Yes` to query `non_blanket_impls` while using + // `SimplifyParams::No` while actually adding them. // - // I think we'll cross that bridge when we get to it. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { + // This way, when searching for some impl for `T: Trait`, we do not look at any impls + // whose outer level is not a parameter or projection. Especially for things like + // `T: Clone` this is incredibly useful as we would otherwise look at all the impls + // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -238,7 +227,9 @@ continue; } - if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No) + { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use crate::ty::fold::TypeFolder; +use crate::ty::fold::{FallibleTypeFolder, TypeFolder}; use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; @@ -788,10 +788,14 @@ [component_ty] => component_ty, _ => self, }; + // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.needs_drop_raw(param_env.and(erased)) + // If normalization fails, we just use `query_ty`. + let query_ty = + tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty); + + tcx.needs_drop_raw(param_env.and(query_ty)) } } } @@ -977,7 +981,7 @@ /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. -pub fn needs_drop_components( +pub fn needs_drop_components<'tcx>( ty: Ty<'tcx>, target_layout: &TargetDataLayout, ) -> Result; 2]>, AlwaysRequiresDrop> { @@ -1046,25 +1050,31 @@ list: &'tcx ty::List, folder: &mut F, intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List, -) -> &'tcx ty::List +) -> Result<&'tcx ty::List, F::Error> where - F: TypeFolder<'tcx>, + F: FallibleTypeFolder<'tcx>, T: TypeFoldable<'tcx> + PartialEq + Copy, { let mut iter = list.iter(); // Look for the first element that changed - if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| { - let new_t = t.fold_with(folder); - if new_t == t { None } else { Some((i, new_t)) } + match iter.by_ref().enumerate().find_map(|(i, t)| match t.try_fold_with(folder) { + Ok(new_t) if new_t == t => None, + new_t => Some((i, new_t)), }) { - // An element changed, prepare to intern the resulting list - let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); - new_list.extend_from_slice(&list[..i]); - new_list.push(new_t); - new_list.extend(iter.map(|t| t.fold_with(folder))); - intern(folder.tcx(), &new_list) - } else { - list + Some((i, Ok(new_t))) => { + // An element changed, prepare to intern the resulting list + let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); + new_list.extend_from_slice(&list[..i]); + new_list.push(new_t); + for t in iter { + new_list.push(t.try_fold_with(folder)?) + } + Ok(intern(folder.tcx(), &new_list)) + } + Some((_, Err(err))) => { + return Err(err); + } + None => Ok(list), } } @@ -1073,7 +1083,7 @@ /// Normalizes all opaque types in the given value, replacing them /// with their underlying types. -pub fn normalize_opaque_types( +pub fn normalize_opaque_types<'tcx>( tcx: TyCtxt<'tcx>, val: &'tcx List>, ) -> &'tcx List> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/walk.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/walk.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/walk.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_middle/src/ty/walk.rs 2022-02-23 04:07:21.000000000 +0000 @@ -69,7 +69,7 @@ } } -impl GenericArg<'tcx> { +impl<'tcx> GenericArg<'tcx> { /// Iterator that walks `self` and any types reachable from /// `self`, in depth-first order. Note that just walks the types /// that appear in `self`, it does not descend into the fields of diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/expr/into.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/expr/into.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/expr/into.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/expr/into.rs 2022-02-23 04:07:21.000000000 +0000 @@ -377,7 +377,7 @@ }) }); let adt = Box::new(AggregateKind::Adt( - adt_def, + adt_def.did, variant_index, substs, user_ty, @@ -467,8 +467,12 @@ } else { Some(destination_block) }, + cleanup: None, }, ); + if options.contains(InlineAsmOptions::MAY_UNWIND) { + this.diverge_from(block); + } destination_block.unit() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/scope.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/scope.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/scope.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/build/scope.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1034,6 +1034,7 @@ | TerminatorKind::Call { .. } | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::InlineAsm { .. } ), "diverge_from called on block with terminator that cannot unwind." ); @@ -1373,7 +1374,8 @@ | TerminatorKind::DropAndReplace { unwind, .. } | TerminatorKind::FalseUnwind { unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. } - | TerminatorKind::Assert { cleanup: unwind, .. } => { + | TerminatorKind::Assert { cleanup: unwind, .. } + | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { *unwind = Some(to); } TerminatorKind::Goto { .. } @@ -1384,8 +1386,7 @@ | TerminatorKind::Unreachable | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => { + | TerminatorKind::FalseEdge { .. } => { span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,7 +5,6 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(once_cell)] #![feature(min_specialization)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/constant.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/constant.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/constant.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/constant.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,7 +46,9 @@ (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(*n, *fty, neg), + (ast::LitKind::Float(n, _), ty::Float(fty)) => { + parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)? + } (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), @@ -55,14 +57,15 @@ Ok(ty::Const::from_value(tcx, lit, ty)) } -fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tcx> { +fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Option> { let num = num.as_str(); use rustc_apfloat::ieee::{Double, Single}; let scalar = match fty { ty::FloatTy::F32 => { - let rust_f = num - .parse::() - .unwrap_or_else(|e| panic!("f32 failed to parse `{}`: {:?}", num, e)); + let rust_f = match num.parse::() { + Ok(f) => f, + Err(_) => return None, + }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) }); @@ -82,9 +85,10 @@ Scalar::from_f32(f) } ty::FloatTy::F64 => { - let rust_f = num - .parse::() - .unwrap_or_else(|e| panic!("f64 failed to parse `{}`: {:?}", num, e)); + let rust_f = match num.parse::() { + Ok(f) => f, + Err(_) => return None, + }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) }); @@ -105,5 +109,5 @@ } }; - ConstValue::Scalar(scalar) + Some(ConstValue::Scalar(scalar)) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -583,9 +583,12 @@ ExprKind::ConstBlock { value } } // Now comes the rote stuff: - hir::ExprKind::Repeat(ref v, ref count) => { - let count_def_id = self.tcx.hir().local_def_id(count.hir_id); - let count = ty::Const::from_anon_const(self.tcx, count_def_id); + hir::ExprKind::Repeat(ref v, _) => { + let ty = self.typeck_results().expr_ty(expr); + let count = match ty.kind() { + ty::Array(_, ct) => ct, + _ => span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty), + }; ExprKind::Repeat { value: self.mirror_expr(v), count } } @@ -605,9 +608,10 @@ }, Err(err) => bug!("invalid loop id for continue: {}", err), }, - hir::ExprKind::Let(ref pat, ref expr, _) => { - ExprKind::Let { expr: self.mirror_expr(expr), pat: self.pattern_from_hir(pat) } - } + hir::ExprKind::Let(let_expr) => ExprKind::Let { + expr: self.mirror_expr(let_expr.init), + pat: self.pattern_from_hir(let_expr.pat), + }, hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { if_then_scope: region::Scope { id: then.hir_id.local_id, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/check_match.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/check_match.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/check_match.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/check_match.rs 2022-02-23 04:07:21.000000000 +0000 @@ -64,7 +64,9 @@ intravisit::walk_expr(self, ex); match &ex.kind { hir::ExprKind::Match(scrut, arms, source) => self.check_match(scrut, arms, *source), - hir::ExprKind::Let(pat, scrut, span) => self.check_let(pat, scrut, *span), + hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => { + self.check_let(pat, init, *span) + } _ => {} } } @@ -148,9 +150,9 @@ } } - fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) { + fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, scrutinee: &hir::Expr<'_>, span: Span) { self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(expr.hir_id); + let mut cx = self.new_cx(scrutinee.hir_id); let tpat = self.lower_pattern(&mut cx, pat, &mut false); check_let_reachability(&mut cx, pat.hir_id, tpat, span); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_build/src/thir/pattern/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -533,43 +533,64 @@ } } + /// Converts inline const patterns. + fn lower_inline_const( + &mut self, + anon_const: &'tcx hir::AnonConst, + id: hir::HirId, + span: Span, + ) -> PatKind<'tcx> { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); + + // Evaluate early like we do in `lower_path`. + let value = value.eval(self.tcx, self.param_env); + + match value.val { + ConstKind::Param(_) => { + self.errors.push(PatternError::ConstParamInPattern(span)); + return PatKind::Wild; + } + ConstKind::Unevaluated(_) => { + // If we land here it means the const can't be evaluated because it's `TooGeneric`. + self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + return PatKind::Wild; + } + _ => (), + } + + *self.const_to_pat(value, id, span, false).kind + } + /// Converts literals, paths and negation of literals to patterns. /// The special case for negation exists to allow things like `-128_i8` /// which would overflow if we tried to evaluate `128_i8` and then negate /// afterwards. fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { - if let hir::ExprKind::Path(ref qpath) = expr.kind { - *self.lower_path(qpath, expr.hir_id, expr.span).kind - } else { - let (lit, neg) = match expr.kind { - hir::ExprKind::ConstBlock(ref anon_const) => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); - if matches!(value.val, ConstKind::Param(_)) { - let span = self.tcx.hir().span(anon_const.hir_id); - self.errors.push(PatternError::ConstParamInPattern(span)); - return PatKind::Wild; - } - return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; - } - hir::ExprKind::Lit(ref lit) => (lit, false), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { - let lit = match expr.kind { - hir::ExprKind::Lit(ref lit) => lit, - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - (lit, true) - } - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - - let lit_input = - LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; - match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, - Err(LitToConstError::Reported) => PatKind::Wild, - Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), + let (lit, neg) = match expr.kind { + hir::ExprKind::Path(ref qpath) => { + return *self.lower_path(qpath, expr.hir_id, expr.span).kind; + } + hir::ExprKind::ConstBlock(ref anon_const) => { + return self.lower_inline_const(anon_const, expr.hir_id, expr.span); } + hir::ExprKind::Lit(ref lit) => (lit, false), + hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { + let lit = match expr.kind { + hir::ExprKind::Lit(ref lit) => lit, + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + (lit, true) + } + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + + let lit_input = + LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; + match self.tcx.at(expr.span).lit_to_const(lit_input) { + Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, + Err(LitToConstError::Reported) => PatKind::Wild, + Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/direction.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/direction.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/direction.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/direction.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,9 @@ use std::ops::RangeInclusive; use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget}; +use super::{ + Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget, +}; pub trait Direction { fn is_forward() -> bool; @@ -16,7 +18,7 @@ /// Applies all effects between the given `EffectIndex`s. /// /// `effects.start()` must precede or equal `effects.end()` in this direction. - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -25,7 +27,7 @@ ) where A: Analysis<'tcx>; - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -33,7 +35,7 @@ ) where A: Analysis<'tcx>; - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -41,7 +43,7 @@ ) where A: GenKillAnalysis<'tcx>; - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -50,7 +52,7 @@ ) where R: ResultsVisitable<'tcx, FlowState = F>; - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, @@ -70,7 +72,7 @@ false } - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -90,7 +92,7 @@ } } - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -110,7 +112,7 @@ } } - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -187,7 +189,7 @@ analysis.apply_statement_effect(state, statement, location); } - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -219,7 +221,7 @@ vis.visit_block_start(state, block_data, block); } - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, _tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, @@ -235,14 +237,26 @@ // Apply terminator-specific edge effects. // // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally. - mir::TerminatorKind::Call { - destination: Some((return_place, dest)), - ref func, - ref args, - .. + mir::TerminatorKind::Call { destination: Some((return_place, dest)), .. } + if dest == bb => + { + let mut tmp = exit_state.clone(); + analysis.apply_call_return_effect( + &mut tmp, + pred, + CallReturnPlaces::Call(return_place), + ); + propagate(pred, &tmp); + } + mir::TerminatorKind::InlineAsm { + destination: Some(dest), ref operands, .. } if dest == bb => { let mut tmp = exit_state.clone(); - analysis.apply_call_return_effect(&mut tmp, pred, func, args, return_place); + analysis.apply_call_return_effect( + &mut tmp, + pred, + CallReturnPlaces::InlineAsm(operands), + ); propagate(pred, &tmp); } @@ -258,6 +272,7 @@ | mir::TerminatorKind::Drop { unwind: Some(unwind), .. } | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. } | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. } + | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. } if unwind == bb => { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { @@ -279,7 +294,7 @@ true } - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -299,7 +314,7 @@ analysis.apply_terminator_effect(state, terminator, location); } - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -319,7 +334,7 @@ analysis.terminator_effect(trans, terminator, location); } - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -392,7 +407,7 @@ } } - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -423,7 +438,7 @@ vis.visit_block_end(state, block_data, block); } - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, _tcx: TyCtxt<'tcx>, _body: &mir::Body<'tcx>, @@ -467,7 +482,7 @@ propagate(target, exit_state); } - Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => { + Call { cleanup, destination, func: _, args: _, from_hir_call: _, fn_span: _ } => { if let Some(unwind) = cleanup { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { propagate(unwind, exit_state); @@ -477,13 +492,37 @@ if let Some((dest_place, target)) = destination { // N.B.: This must be done *last*, otherwise the unwind path will see the call // return effect. - analysis.apply_call_return_effect(exit_state, bb, func, args, dest_place); + analysis.apply_call_return_effect( + exit_state, + bb, + CallReturnPlaces::Call(dest_place), + ); propagate(target, exit_state); } } - InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => { + InlineAsm { + template: _, + ref operands, + options: _, + line_spans: _, + destination, + cleanup, + } => { + if let Some(unwind) = cleanup { + if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { + propagate(unwind, exit_state); + } + } + if let Some(target) = destination { + // N.B.: This must be done *last*, otherwise the unwind path will see the call + // return effect. + analysis.apply_call_return_effect( + exit_state, + bb, + CallReturnPlaces::InlineAsm(operands), + ); propagate(target, exit_state); } } @@ -552,7 +591,7 @@ // // FIXME: Figure out how to express this using `Option::clone_from`, or maybe lift it into the // standard library? -fn opt_clone_from_or_clone(opt: &'a mut Option, val: &T) -> &'a mut T { +fn opt_clone_from_or_clone<'a, T: Clone>(opt: &'a mut Option, val: &T) -> &'a mut T { if opt.is_some() { let ret = opt.as_mut().unwrap(); ret.clone_from(val); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/engine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/engine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/engine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/engine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,12 +31,15 @@ pub(super) entry_sets: IndexVec, } -impl Results<'tcx, A> +impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn into_results_cursor(self, body: &'mir mir::Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> { + pub fn into_results_cursor<'mir>( + self, + body: &'mir mir::Body<'tcx>, + ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, self) } @@ -45,7 +48,7 @@ &self.entry_sets[block] } - pub fn visit_with( + pub fn visit_with<'mir>( &self, body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, @@ -54,7 +57,7 @@ visit_results(body, blocks, self, vis) } - pub fn visit_reachable_with( + pub fn visit_reachable_with<'mir>( &self, body: &'mir mir::Body<'tcx>, vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = A::Domain>, @@ -85,7 +88,7 @@ apply_trans_for_block: Option>, } -impl Engine<'a, 'tcx, A> +impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> where A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, D: Clone + JoinSemiLattice + GenKill + BorrowMut>, @@ -119,7 +122,7 @@ } } -impl Engine<'a, 'tcx, A> +impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> where A: Analysis<'tcx, Domain = D>, D: Clone + JoinSemiLattice, @@ -257,7 +260,7 @@ /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes. -fn write_graphviz_results( +fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, results: &Results<'tcx, A>, @@ -330,7 +333,7 @@ } impl RustcMirAttrs { - fn parse(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result { + fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { let attrs = tcx.get_attrs(def_id); let mut result = Ok(()); @@ -373,7 +376,7 @@ fn set_field( field: &mut Option, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, attr: &ast::NestedMetaItem, mapper: impl FnOnce(Symbol) -> Result, ) -> Result<(), ()> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/graphviz.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/graphviz.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/graphviz.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/graphviz.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ use rustc_middle::mir::{self, BasicBlock, Body, Location}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{Analysis, Direction, Results, ResultsRefCursor, ResultsVisitor}; +use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum OutputStyle { @@ -36,7 +36,7 @@ style: OutputStyle, } -impl Formatter<'a, 'tcx, A> +impl<'a, 'tcx, A> Formatter<'a, 'tcx, A> where A: Analysis<'tcx>, { @@ -52,7 +52,7 @@ index: usize, } -fn dataflow_successors(body: &Body<'tcx>, bb: BasicBlock) -> Vec { +fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec { body[bb] .terminator() .successors() @@ -61,7 +61,7 @@ .collect() } -impl dot::Labeller<'_> for Formatter<'a, 'tcx, A> +impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -100,7 +100,7 @@ } } -impl dot::GraphWalk<'a> for Formatter<'a, 'tcx, A> +impl<'a, 'tcx, A> dot::GraphWalk<'a> for Formatter<'a, 'tcx, A> where A: Analysis<'tcx>, { @@ -138,7 +138,7 @@ style: OutputStyle, } -impl BlockFormatter<'a, 'tcx, A> +impl<'a, 'tcx, A> BlockFormatter<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -231,16 +231,15 @@ // for the basic block itself. That way, we could display terminator-specific effects for // backward dataflow analyses as well as effects for `SwitchInt` terminators. match terminator.kind { - mir::TerminatorKind::Call { - destination: Some((return_place, _)), - ref func, - ref args, - .. - } => { + mir::TerminatorKind::Call { destination: Some((return_place, _)), .. } => { self.write_row(w, "", "(on successful return)", |this, w, fmt| { let state_on_unwind = this.results.get().clone(); this.results.apply_custom_effect(|analysis, state| { - analysis.apply_call_return_effect(state, block, func, args, return_place); + analysis.apply_call_return_effect( + state, + block, + CallReturnPlaces::Call(return_place), + ); }); write!( @@ -278,6 +277,31 @@ })?; } + mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => { + self.write_row(w, "", "(on successful return)", |this, w, fmt| { + let state_on_unwind = this.results.get().clone(); + this.results.apply_custom_effect(|analysis, state| { + analysis.apply_call_return_effect( + state, + block, + CallReturnPlaces::InlineAsm(operands), + ); + }); + + write!( + w, + r#"{diff}"#, + colspan = this.style.num_state_columns(), + fmt = fmt, + diff = diff_pretty( + this.results.get(), + &state_on_unwind, + this.results.analysis() + ), + ) + })?; + } + _ => {} }; @@ -467,7 +491,7 @@ after: Vec, } -impl StateDiffCollector<'a, 'tcx, A> +impl<'a, 'tcx, A> StateDiffCollector<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -490,7 +514,7 @@ } } -impl ResultsVisitor<'a, 'tcx> for StateDiffCollector<'a, 'tcx, A> +impl<'a, 'tcx, A> ResultsVisitor<'a, 'tcx> for StateDiffCollector<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -500,7 +524,7 @@ fn visit_block_start( &mut self, state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, + _block_data: &mir::BasicBlockData<'tcx>, _block: BasicBlock, ) { if A::Direction::is_forward() { @@ -511,7 +535,7 @@ fn visit_block_end( &mut self, state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, + _block_data: &mir::BasicBlockData<'tcx>, _block: BasicBlock, ) { if A::Direction::is_backward() { @@ -522,7 +546,7 @@ fn visit_statement_before_primary_effect( &mut self, state: &Self::FlowState, - _statement: &'mir mir::Statement<'tcx>, + _statement: &mir::Statement<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { @@ -534,7 +558,7 @@ fn visit_statement_after_primary_effect( &mut self, state: &Self::FlowState, - _statement: &'mir mir::Statement<'tcx>, + _statement: &mir::Statement<'tcx>, _location: Location, ) { self.after.push(diff_pretty(state, &self.prev_state, self.analysis)); @@ -544,7 +568,7 @@ fn visit_terminator_before_primary_effect( &mut self, state: &Self::FlowState, - _terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { @@ -556,7 +580,7 @@ fn visit_terminator_after_primary_effect( &mut self, state: &Self::FlowState, - _terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, ) { self.after.push(diff_pretty(state, &self.prev_state, self.analysis)); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -160,9 +160,7 @@ &self, state: &mut Self::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ); /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator. @@ -216,7 +214,11 @@ /// .iterate_to_fixpoint() /// .into_results_cursor(body); /// ``` - fn into_engine(self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Engine<'mir, 'tcx, Self> + fn into_engine<'mir>( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + ) -> Engine<'mir, 'tcx, Self> where Self: Sized, { @@ -276,9 +278,7 @@ &self, trans: &mut impl GenKill, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ); /// See `Analysis::apply_yield_resume_effect`. @@ -300,7 +300,7 @@ } } -impl Analysis<'tcx> for A +impl<'tcx, A> Analysis<'tcx> for A where A: GenKillAnalysis<'tcx>, A::Domain: GenKill + BorrowMut>, @@ -347,11 +347,9 @@ &self, state: &mut A::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - self.call_return_effect(state, block, func, args, return_place); + self.call_return_effect(state, block, return_places); } fn apply_yield_resume_effect( @@ -374,7 +372,11 @@ /* Extension methods */ - fn into_engine(self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Engine<'mir, 'tcx, Self> + fn into_engine<'mir>( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + ) -> Engine<'mir, 'tcx, Self> where Self: Sized, { @@ -542,5 +544,29 @@ fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)); } +/// List of places that are written to after a successful (non-unwind) return +/// from a `Call` or `InlineAsm`. +pub enum CallReturnPlaces<'a, 'tcx> { + Call(mir::Place<'tcx>), + InlineAsm(&'a [mir::InlineAsmOperand<'tcx>]), +} + +impl<'tcx> CallReturnPlaces<'_, 'tcx> { + pub fn for_each(&self, mut f: impl FnMut(mir::Place<'tcx>)) { + match *self { + Self::Call(place) => f(place), + Self::InlineAsm(operands) => { + for op in operands { + match *op { + mir::InlineAsmOperand::Out { place: Some(place), .. } + | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place), + _ => {} + } + } + } + } + } +} + #[cfg(test)] mod tests; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -85,7 +85,7 @@ dir: PhantomData, } -impl MockAnalysis<'tcx, D> { +impl MockAnalysis<'_, D> { const BASIC_BLOCK_OFFSET: usize = 100; /// The entry set for each `BasicBlock` is the ID of that block offset by a fixed amount to @@ -160,7 +160,7 @@ } } -impl AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { type Domain = BitSet; type Direction = D; @@ -175,7 +175,7 @@ } } -impl Analysis<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { fn apply_statement_effect( &self, state: &mut Self::Domain, @@ -220,9 +220,7 @@ &self, _state: &mut Self::Domain, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _return_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } @@ -262,7 +260,7 @@ } } -fn test_cursor(analysis: MockAnalysis<'tcx, D>) { +fn test_cursor(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/visitor.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/visitor.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/visitor.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/framework/visitor.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,7 @@ /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. -pub fn visit_results( +pub fn visit_results<'mir, 'tcx, F, V>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, results: &V, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,6 @@ use super::*; -use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -45,7 +45,7 @@ } } -impl AnalysisDomain<'tcx> for MaybeBorrowedLocals { +impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_borrowed_locals"; @@ -59,7 +59,7 @@ } } -impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { type Idx = Local; fn statement_effect( @@ -84,9 +84,7 @@ &self, _trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } @@ -97,7 +95,7 @@ ignore_borrow_on_drop: bool, } -impl Visitor<'tcx> for TransferFunction<'a, T> +impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T> where T: GenKill, { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/init_locals.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/init_locals.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/init_locals.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/init_locals.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ //! //! A local will be maybe initialized if *any* projections of that local might be initialized. -use crate::GenKill; +use crate::{CallReturnPlaces, GenKill}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; @@ -10,7 +10,7 @@ pub struct MaybeInitializedLocals; -impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_init_locals"; @@ -28,7 +28,7 @@ } } -impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { type Idx = Local; fn statement_effect( @@ -53,11 +53,9 @@ &self, trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - trans.gen(return_place.local) + return_places.for_each(|place| trans.gen(place.local)); } /// See `Analysis::apply_yield_resume_effect`. @@ -75,7 +73,7 @@ trans: &'a mut T, } -impl Visitor<'tcx> for TransferFunction<'a, T> +impl Visitor<'_> for TransferFunction<'_, T> where T: GenKill, { @@ -83,7 +81,11 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext}; match context { // These are handled specially in `call_return_effect` and `yield_resume_effect`. - PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {} + PlaceContext::MutatingUse( + MutatingUseContext::Call + | MutatingUseContext::AsmOutput + | MutatingUseContext::Yield, + ) => {} // Otherwise, when a place is mutated, we must consider it possibly initialized. PlaceContext::MutatingUse(_) => self.trans.gen(local), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/liveness.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/liveness.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/liveness.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/liveness.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Local, Location}; -use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis}; /// A [live-variable dataflow analysis][liveness]. /// @@ -48,12 +48,12 @@ pub struct MaybeLiveLocals; impl MaybeLiveLocals { - fn transfer_function(&self, trans: &'a mut T) -> TransferFunction<'a, T> { + fn transfer_function<'a, T>(&self, trans: &'a mut T) -> TransferFunction<'a, T> { TransferFunction(trans) } } -impl AnalysisDomain<'tcx> for MaybeLiveLocals { +impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { type Domain = BitSet; type Direction = Backward; @@ -69,7 +69,7 @@ } } -impl GenKillAnalysis<'tcx> for MaybeLiveLocals { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { type Idx = Local; fn statement_effect( @@ -94,13 +94,13 @@ &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - if let Some(local) = dest_place.as_local() { - trans.kill(local); - } + return_places.for_each(|place| { + if let Some(local) = place.as_local() { + trans.kill(local); + } + }); } fn yield_resume_effect( @@ -167,12 +167,16 @@ // destination place for a `Call` return or `Yield` resume respectively. Since this is // only a `Def` when the function returns successfully, we handle this case separately // in `call_return_effect` above. - PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => None, + PlaceContext::MutatingUse( + MutatingUseContext::Call + | MutatingUseContext::AsmOutput + | MutatingUseContext::Yield, + ) => None, // All other contexts are uses... PlaceContext::MutatingUse( MutatingUseContext::AddressOf - | MutatingUseContext::AsmOutput + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::Borrow | MutatingUseContext::Drop | MutatingUseContext::Retag, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ use crate::drop_flag_effects_for_function_entry; use crate::drop_flag_effects_for_location; use crate::elaborate_drops::DropFlagState; -use crate::framework::SwitchIntEdgeEffects; +use crate::framework::{CallReturnPlaces, SwitchIntEdgeEffects}; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::on_lookup_result_bits; use crate::MoveDataParamEnv; @@ -354,21 +354,21 @@ &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, - ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 1 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.gen(mpi); - }, - ); + return_places: CallReturnPlaces<'_, 'tcx>, + ) { + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 1 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.gen(mpi); + }, + ); + }); } fn switch_int_edge_effects>( @@ -472,21 +472,21 @@ &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, - ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 0 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.kill(mpi); - }, - ); + return_places: CallReturnPlaces<'_, 'tcx>, + ) { + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 0 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.kill(mpi); + }, + ); + }); } fn switch_int_edge_effects>( @@ -591,21 +591,21 @@ &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, - ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 1 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.gen(mpi); - }, - ); + return_places: CallReturnPlaces<'_, 'tcx>, + ) { + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 1 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.gen(mpi); + }, + ); + }); } } @@ -679,9 +679,7 @@ &self, trans: &mut impl GenKill, block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { let move_data = self.move_data(); let init_loc_map = &move_data.init_loc_map; @@ -706,7 +704,7 @@ /// /// If the basic block matches this pattern, this function returns the place corresponding to the /// enum (`_1` in the example above) as well as the `AdtDef` of that enum. -fn switch_on_enum_discriminant( +fn switch_on_enum_discriminant<'mir, 'tcx>( tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, block: &'mir mir::BasicBlockData<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ pub use super::*; use crate::storage::AlwaysLiveLocals; -use crate::{GenKill, Results, ResultsRefCursor}; +use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor}; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use std::cell::RefCell; @@ -17,7 +17,7 @@ } } -impl crate::AnalysisDomain<'tcx> for MaybeStorageLive { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -39,7 +39,7 @@ } } -impl crate::GenKillAnalysis<'tcx> for MaybeStorageLive { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive { type Idx = Local; fn statement_effect( @@ -68,9 +68,7 @@ &self, _trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _return_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { // Nothing to do when a call returns successfully } @@ -226,7 +224,7 @@ terminator: &mir::Terminator<'tcx>, loc: Location, ) { - match &terminator.kind { + match terminator.kind { // For call terminators the destination requires storage for the call // and after the call returns successfully, but not after a panic. // Since `propagate_call_unwind` doesn't exist, we have to kill the @@ -235,6 +233,11 @@ trans.kill(place.local); } + // The same applies to InlineAsm outputs. + TerminatorKind::InlineAsm { ref operands, .. } => { + CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local)); + } + // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Call { destination: None, .. } @@ -247,7 +250,6 @@ | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Goto { .. } - | TerminatorKind::InlineAsm { .. } | TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } @@ -261,11 +263,9 @@ &self, trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - trans.gen(return_place.local); + return_places.for_each(|place| trans.gen(place.local)); } fn yield_resume_effect( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,8 +3,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(exact_size_is_empty)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] @@ -28,9 +26,9 @@ on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, - Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor, - ResultsVisitable, ResultsVisitor, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces, + Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, + ResultsRefCursor, ResultsVisitable, ResultsVisitor, }; use self::move_paths::MoveData; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/move_paths/builder.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/move_paths/builder.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/move_paths/builder.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/move_paths/builder.rs 2022-02-23 04:07:21.000000000 +0000 @@ -343,19 +343,7 @@ | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) - | Rvalue::NullaryOp(NullOp::Box, _) => { - // This returns an rvalue with uninitialized contents. We can't - // move out of it here because it is an rvalue - assignments always - // completely initialize their place. - // - // However, this does not matter - MIR building is careful to - // only emit a shallow free for the partially-initialized - // temporary. - // - // In any case, if we want to fix this, we have to register a - // special move and change the `statement_effect` functions. - } + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} } } @@ -419,6 +407,7 @@ options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/rustc_peek.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/rustc_peek.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/rustc_peek.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/rustc_peek.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,6 +20,7 @@ pub struct SanityCheck; +// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { use crate::has_rustc_mir_with; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/storage.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/storage.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/storage.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_dataflow/src/storage.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ pub struct AlwaysLiveLocals(BitSet); impl AlwaysLiveLocals { - pub fn new(body: &mir::Body<'tcx>) -> Self { + pub fn new(body: &mir::Body<'_>) -> Self { let mut always_live_locals = AlwaysLiveLocals(BitSet::new_filled(body.local_decls.len())); for block in body.basic_blocks() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/add_retag.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/add_retag.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/add_retag.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/add_retag.rs 2022-02-23 04:07:21.000000000 +0000 @@ -34,7 +34,7 @@ } /// Determine whether this type may be a reference (or box), and thus needs retagging. -fn may_be_reference(ty: Ty<'tcx>) -> bool { +fn may_be_reference(ty: Ty<'_>) -> bool { match ty.kind() { // Primitive types that are not references ty::Bool @@ -58,11 +58,11 @@ } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !tcx.sess.opts.debugging_opts.mir_emit_retag { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.debugging_opts.mir_emit_retag + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // We need an `AllCallEdges` pass before we can do any work. super::add_call_guards::AllCallEdges.run_pass(tcx, body); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_const_item_mutation.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_const_item_mutation.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_const_item_mutation.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_const_item_mutation.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,12 +6,12 @@ use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; -use crate::MirPass; +use crate::MirLint; pub struct CheckConstItemMutation; -impl<'tcx> MirPass<'tcx> for CheckConstItemMutation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for CheckConstItemMutation { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(&body); } @@ -23,7 +23,7 @@ target_local: Option, } -impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> { +impl<'tcx> ConstMutationChecker<'_, 'tcx> { fn is_const_item(&self, local: Local) -> Option { if let Some(box LocalInfo::ConstRef { def_id }) = self.body.local_decls[local].local_info { Some(def_id) @@ -95,7 +95,7 @@ } } -impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) { if let StatementKind::Assign(box (lhs, _)) = &stmt.kind { // Check for assignment to fields of a constant diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_packed_ref.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_packed_ref.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_packed_ref.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_packed_ref.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,7 @@ use rustc_span::symbol::sym; use crate::util; -use crate::MirPass; +use crate::MirLint; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; @@ -15,8 +15,8 @@ pub struct CheckPackedRef; -impl<'tcx> MirPass<'tcx> for CheckPackedRef { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for CheckPackedRef { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; @@ -66,7 +66,7 @@ } } -impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. self.source_info = terminator.source_info; @@ -105,6 +105,11 @@ a misaligned reference is undefined behavior (even if that \ reference is never dereferenced)", ) + .help( + "copy the field contents to a local variable, or replace the \ + reference with a raw pointer and use `read_unaligned`/`write_unaligned` \ + (loads and stores via `*p` must be properly aligned even when using raw pointers)" + ) .emit() }, ); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_unsafety.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_unsafety.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_unsafety.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/check_unsafety.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,7 +46,7 @@ } } -impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { self.source_info = terminator.source_info; match terminator.kind { @@ -117,8 +117,8 @@ match rvalue { Rvalue::Aggregate(box ref aggregate, _) => match aggregate { &AggregateKind::Array(..) | &AggregateKind::Tuple => {} - &AggregateKind::Adt(ref def, ..) => { - match self.tcx.layout_scalar_valid_range(def.did) { + &AggregateKind::Adt(adt_did, ..) => { + match self.tcx.layout_scalar_valid_range(adt_did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.require_unsafe( UnsafetyViolationKind::General, @@ -208,6 +208,7 @@ MutatingUseContext::Store | MutatingUseContext::Drop | MutatingUseContext::AsmOutput + | MutatingUseContext::LlvmAsmOutput ) ); // If this is just an assignment, determine if the assigned type needs dropping. @@ -243,7 +244,7 @@ } } -impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { +impl<'tcx> UnsafetyChecker<'_, 'tcx> { fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) { // Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such. assert_ne!(kind, UnsafetyViolationKind::UnsafeFn); @@ -396,7 +397,7 @@ unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>, } -impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> { +impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_debuginfo.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_debuginfo.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_debuginfo.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_debuginfo.rs 2022-02-23 04:07:21.000000000 +0000 @@ -15,11 +15,11 @@ pub struct ConstDebugInfo; impl<'tcx> MirPass<'tcx> for ConstDebugInfo { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0 + } + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running ConstDebugInfo on {:?}", body.source); for (local, constant) in find_optimization_oportunities(body) { @@ -89,7 +89,7 @@ eligable_locals } -impl<'tcx> Visitor<'tcx> for LocalUseVisitor { +impl Visitor<'_> for LocalUseVisitor { fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) { if context.is_mutating_use() { self.local_mutating_uses[*local] = self.local_mutating_uses[*local].saturating_add(1); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_goto.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_goto.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_goto.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_goto.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,10 +27,11 @@ pub struct ConstGoto; impl<'tcx> MirPass<'tcx> for ConstGoto { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } trace!("Running ConstGoto on {:?}", body.source); let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let mut opt_finder = @@ -53,7 +54,7 @@ } } -impl<'a, 'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { let _: Option<_> = try { let target = terminator.kind.as_goto()?; @@ -82,20 +83,7 @@ // Now find which value in the Switch matches the const value. let const_value = _const.literal.try_eval_bits(self.tcx, self.param_env, switch_ty)?; - let found_value_idx_option = targets - .iter() - .enumerate() - .find(|(_, (value, _))| const_value == *value) - .map(|(idx, _)| idx); - - let target_to_use_in_goto = - if let Some(found_value_idx) = found_value_idx_option { - targets.iter().nth(found_value_idx).unwrap().1 - } else { - // If we did not find the const value in values, it must be the otherwise case - targets.otherwise() - }; - + let target_to_use_in_goto = targets.target_for_value(const_value); self.optimizations.push(OptimizationToApply { bb_with_goto: location.block, target_to_use_in_goto, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_prop.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_prop.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_prop.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/const_prop.rs 2022-02-23 04:07:21.000000000 +0000 @@ -62,6 +62,13 @@ pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { + fn is_enabled(&self, _sess: &rustc_session::Session) -> bool { + // FIXME(#70073): Unlike the other passes in "optimizations", this one emits errors, so it + // runs even when MIR optimizations are disabled. We should separate the lint out from the + // transform and move the lint as early in the pipeline as possible. + true + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if body.source.promoted.is_some() { @@ -164,7 +171,7 @@ can_const_prop: IndexVec, } -impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { +impl ConstPropMachine<'_, '_> { fn new( only_propagate_inside_block_locals: BitSet, can_const_prop: IndexVec, @@ -200,7 +207,7 @@ _args: &[OpTy<'tcx>], _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>, _unwind: StackPopUnwind, - ) -> InterpResult<'tcx, Option<&'mir Body<'tcx>>> { + ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { Ok(None) } @@ -232,13 +239,6 @@ throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } - fn box_alloc( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _dest: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - throw_machine_stop_str!("can't const prop heap allocations") - } - fn access_local( _ecx: &InterpCx<'mir, 'tcx, Self>, frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, @@ -301,14 +301,14 @@ } #[inline(always)] - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] { &ecx.machine.stack } #[inline(always)] - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec> { &mut ecx.machine.stack @@ -329,7 +329,7 @@ source_info: Option, } -impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -338,21 +338,21 @@ } } -impl<'mir, 'tcx> HasDataLayout for ConstPropagator<'mir, 'tcx> { +impl HasDataLayout for ConstPropagator<'_, '_> { #[inline] fn data_layout(&self) -> &TargetDataLayout { &self.tcx.data_layout } } -impl<'mir, 'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } } -impl<'mir, 'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env @@ -406,7 +406,7 @@ Instance::new(def_id, substs), dummy_body, ret.as_ref(), - StackPopCleanup::None { cleanup: false }, + StackPopCleanup::Root { cleanup: false }, ) .expect("failed to push initial stack frame"); @@ -745,62 +745,44 @@ rvalue: &Rvalue<'tcx>, place: Place<'tcx>, ) -> Option<()> { - self.use_ecx(|this| { - match rvalue { - Rvalue::BinaryOp(op, box (left, right)) - | Rvalue::CheckedBinaryOp(op, box (left, right)) => { - let l = this.ecx.eval_operand(left, None); - let r = this.ecx.eval_operand(right, None); - - let const_arg = match (l, r) { - (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, - (Err(e), Err(_)) => return Err(e), - (Ok(_), Ok(_)) => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; - return Ok(()); - } - }; - - let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; - let dest = this.ecx.eval_place(place)?; - - match op { - BinOp::BitAnd => { - if arg_value == 0 { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::BitOr => { - if arg_value == const_arg.layout.size.truncate(u128::MAX) - || (const_arg.layout.ty.is_bool() && arg_value == 1) - { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::Mul => { - if const_arg.layout.ty.is_integral() && arg_value == 0 { - if let Rvalue::CheckedBinaryOp(_, _) = rvalue { - let val = Immediate::ScalarPair( - const_arg.to_scalar()?.into(), - Scalar::from_bool(false).into(), - ); - this.ecx.write_immediate(val, &dest)?; - } else { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + self.use_ecx(|this| match rvalue { + Rvalue::BinaryOp(op, box (left, right)) + | Rvalue::CheckedBinaryOp(op, box (left, right)) => { + let l = this.ecx.eval_operand(left, None); + let r = this.ecx.eval_operand(right, None); + + let const_arg = match (l, r) { + (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, + (Err(e), Err(_)) => return Err(e), + (Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place), + }; + + let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; + let dest = this.ecx.eval_place(place)?; + + match op { + BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest), + BinOp::BitOr + if arg_value == const_arg.layout.size.truncate(u128::MAX) + || (const_arg.layout.ty.is_bool() && arg_value == 1) => + { + this.ecx.write_immediate(*const_arg, &dest) + } + BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => { + if let Rvalue::CheckedBinaryOp(_, _) = rvalue { + let val = Immediate::ScalarPair( + const_arg.to_scalar()?.into(), + Scalar::from_bool(false).into(), + ); + this.ecx.write_immediate(val, &dest) + } else { + this.ecx.write_immediate(*const_arg, &dest) } } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + _ => this.ecx.eval_rvalue_into_place(rvalue, place), } } - - Ok(()) + _ => this.ecx.eval_rvalue_into_place(rvalue, place), }) } @@ -964,7 +946,7 @@ impl CanConstProp { /// Returns true if `local` can be propagated - fn check( + fn check<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, body: &Body<'tcx>, @@ -1012,7 +994,7 @@ } } -impl<'tcx> Visitor<'tcx> for CanConstProp { +impl Visitor<'_> for CanConstProp { fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { @@ -1022,6 +1004,7 @@ // These are just stores, where the storing is not propagatable, but there may be later // mutations of the same local via `Store` | MutatingUse(MutatingUseContext::Call) + | MutatingUse(MutatingUseContext::AsmOutput) // Actual store that can possibly even propagate a value | MutatingUse(MutatingUseContext::Store) => { if !self.found_assignment.insert(local) { @@ -1052,7 +1035,7 @@ // These could be propagated with a smarter analysis or just some careful thinking about // whether they'd be fine right now. - MutatingUse(MutatingUseContext::AsmOutput) + MutatingUse(MutatingUseContext::LlvmAsmOutput) | MutatingUse(MutatingUseContext::Yield) | MutatingUse(MutatingUseContext::Drop) | MutatingUse(MutatingUseContext::Retag) @@ -1071,7 +1054,7 @@ } } -impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/debug.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/debug.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/debug.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/debug.rs 2022-02-23 04:07:21.000000000 +0000 @@ -148,7 +148,7 @@ let mut counter_format = ExpressionFormat::default(); if let Ok(env_debug_options) = std::env::var(RUSTC_COVERAGE_DEBUG_OPTIONS) { - for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(',') { + for setting_str in env_debug_options.replace(' ', "").replace('-', "_").split(',') { let (option, value) = match setting_str.split_once('=') { None => (setting_str, None), Some((k, v)) => (k, Some(v)), @@ -629,7 +629,7 @@ } /// Generates the MIR pass `CoverageSpan`-specific spanview dump file. -pub(super) fn dump_coverage_spanview( +pub(super) fn dump_coverage_spanview<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, basic_coverage_blocks: &CoverageGraph, @@ -651,7 +651,7 @@ } /// Converts the computed `BasicCoverageBlockData`s into `SpanViewable`s. -fn span_viewables( +fn span_viewables<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, basic_coverage_blocks: &CoverageGraph, @@ -670,7 +670,7 @@ } /// Generates the MIR pass coverage-specific graphviz dump file. -pub(super) fn dump_coverage_graphviz( +pub(super) fn dump_coverage_graphviz<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, pass_name: &str, @@ -750,7 +750,7 @@ .expect("Unexpected error writing BasicCoverageBlock graphviz DOT file"); } -fn bcb_to_string_sections( +fn bcb_to_string_sections<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, debug_counters: &DebugCounters, @@ -817,7 +817,7 @@ /// Returns a simple string representation of a `TerminatorKind` variant, independent of any /// values it might hold. -pub(super) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str { +pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { match kind { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/graph.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,7 +27,7 @@ } impl CoverageGraph { - pub fn from_mir(mir_body: &mir::Body<'tcx>) -> Self { + pub fn from_mir(mir_body: &mir::Body<'_>) -> Self { let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body); // Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock @@ -74,7 +74,7 @@ } fn compute_basic_coverage_blocks( - mir_body: &mir::Body<'tcx>, + mir_body: &mir::Body<'_>, ) -> ( IndexVec, IndexVec>, @@ -267,7 +267,7 @@ } } -impl graph::GraphPredecessors<'graph> for CoverageGraph { +impl<'graph> graph::GraphPredecessors<'graph> for CoverageGraph { type Item = BasicCoverageBlock; type Iter = std::iter::Copied>; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -49,6 +49,10 @@ pub struct InstrumentCoverage; impl<'tcx> MirPass<'tcx> for InstrumentCoverage { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.instrument_coverage() + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { let mir_source = mir_body.source; @@ -439,7 +443,7 @@ } fn inject_edge_counter_basic_block( - mir_body: &mut mir::Body<'tcx>, + mir_body: &mut mir::Body<'_>, from_bb: BasicBlock, to_bb: BasicBlock, ) -> BasicBlock { @@ -462,7 +466,7 @@ } fn inject_statement( - mir_body: &mut mir::Body<'tcx>, + mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb: BasicBlock, some_code_region: Option, @@ -484,7 +488,7 @@ } // Non-code expressions are injected into the coverage map, without generating executable code. -fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) { +fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) { debug_assert!(matches!(expression, CoverageKind::Expression { .. })); debug!(" injecting non-code expression {:?}", expression); let inject_in_bb = mir::START_BLOCK; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/query.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/query.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/query.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/query.rs 2022-02-23 04:07:21.000000000 +0000 @@ -137,7 +137,7 @@ coverage_visitor.info } -fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { +fn covered_file_name(tcx: TyCtxt<'_>, def_id: DefId) -> Option { if tcx.is_mir_available(def_id) { let body = mir_body(tcx, def_id); for bb_data in body.basic_blocks().iter() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/spans.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/spans.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/spans.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/spans.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,7 @@ } impl CoverageStatement { - pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String { + pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String { match *self { Self::Statement(bb, span, stmt_index) => { let stmt = &mir_body[bb].statements[stmt_index]; @@ -86,7 +86,7 @@ } pub fn for_statement( - statement: &Statement<'tcx>, + statement: &Statement<'_>, span: Span, expn_span: Span, bcb: BasicCoverageBlock, @@ -151,18 +151,18 @@ self.bcb == other.bcb } - pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String { + pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String { format!( "{}\n {}", source_range_no_file(tcx, &self.span), - self.format_coverage_statements(tcx, mir_body).replace("\n", "\n "), + self.format_coverage_statements(tcx, mir_body).replace('\n', "\n "), ) } - pub fn format_coverage_statements( + pub fn format_coverage_statements<'tcx>( &self, tcx: TyCtxt<'tcx>, - mir_body: &'a mir::Body<'tcx>, + mir_body: &mir::Body<'tcx>, ) -> String { let mut sorted_coverage_statements = self.coverage_statements.clone(); sorted_coverage_statements.sort_unstable_by_key(|covstmt| match *covstmt { @@ -329,9 +329,7 @@ fn mir_to_initial_sorted_coverage_spans(&self) -> Vec { let mut initial_spans = Vec::::with_capacity(self.mir_body.num_nodes() * 2); for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() { - for coverage_span in self.bcb_to_initial_coverage_spans(bcb, bcb_data) { - initial_spans.push(coverage_span); - } + initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data)); } if initial_spans.is_empty() { @@ -803,7 +801,7 @@ /// If the MIR `Statement` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option { +pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option { match statement.kind { // These statements have spans that are often outside the scope of the executed source code // for their parent `BasicBlock`. @@ -847,7 +845,7 @@ /// If the MIR `Terminator` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_terminator_span(terminator: &'a Terminator<'tcx>) -> Option { +pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { match terminator.kind { // These terminators have spans that don't positively contribute to computing a reasonable // span of actually executed source code. (For example, SwitchInt terminators extracted from diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/tests.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/tests.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/tests.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/coverage/tests.rs 2022-02-23 04:07:21.000000000 +0000 @@ -180,7 +180,7 @@ } } -fn debug_basic_blocks(mir_body: &Body<'tcx>) -> String { +fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String { format!( "{:?}", mir_body @@ -273,7 +273,7 @@ } /// Create a mock `Body` with a simple flow. -fn goto_switchint() -> Body<'a> { +fn goto_switchint<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let goto = blocks.goto(Some(start)); @@ -363,7 +363,7 @@ } /// Create a mock `Body` with a loop. -fn switchint_then_loop_else_return() -> Body<'a> { +fn switchint_then_loop_else_return<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let switchint = blocks.switchint(Some(start)); @@ -449,7 +449,7 @@ } /// Create a mock `Body` with nested loops. -fn switchint_loop_then_inner_loop_else_break() -> Body<'a> { +fn switchint_loop_then_inner_loop_else_break<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let switchint = blocks.switchint(Some(start)); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/deduplicate_blocks.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/deduplicate_blocks.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/deduplicate_blocks.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/deduplicate_blocks.rs 2022-02-23 04:07:21.000000000 +0000 @@ -15,10 +15,11 @@ pub struct DeduplicateBlocks; impl<'tcx> MirPass<'tcx> for DeduplicateBlocks { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } debug!("Running DeduplicateBlocks on `{:?}`", body.source); let duplicates = find_duplicates(body); let has_opts_to_apply = !duplicates.is_empty(); @@ -53,7 +54,7 @@ } } -fn find_duplicates<'a, 'tcx>(body: &'a Body<'tcx>) -> FxHashMap { +fn find_duplicates(body: &Body<'_>) -> FxHashMap { let mut duplicates = FxHashMap::default(); let bbs_to_go_through = @@ -101,7 +102,7 @@ basic_block_data: &'a BasicBlockData<'tcx>, } -impl<'tcx, 'a> Hash for BasicBlockHashable<'tcx, 'a> { +impl Hash for BasicBlockHashable<'_, '_> { fn hash(&self, state: &mut H) { hash_statements(state, self.basic_block_data.statements.iter()); // Note that since we only hash the kind, we lose span information if we deduplicate the blocks @@ -109,9 +110,9 @@ } } -impl<'tcx, 'a> Eq for BasicBlockHashable<'tcx, 'a> {} +impl Eq for BasicBlockHashable<'_, '_> {} -impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> { +impl PartialEq for BasicBlockHashable<'_, '_> { fn eq(&self, other: &Self) -> bool { self.basic_block_data.statements.len() == other.basic_block_data.statements.len() && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind @@ -131,7 +132,7 @@ } } -fn statement_hash<'tcx, H: Hasher>(hasher: &mut H, stmt: &StatementKind<'tcx>) { +fn statement_hash(hasher: &mut H, stmt: &StatementKind<'_>) { match stmt { StatementKind::Assign(box (place, rvalue)) => { place.hash(hasher); @@ -141,14 +142,14 @@ }; } -fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'tcx>) { +fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'_>) { match rvalue { Rvalue::Use(op) => operand_hash(hasher, op), x => x.hash(hasher), }; } -fn operand_hash(hasher: &mut H, operand: &Operand<'tcx>) { +fn operand_hash(hasher: &mut H, operand: &Operand<'_>) { match operand { Operand::Constant(box Constant { user_ty: _, literal, span: _ }) => literal.hash(hasher), x => x.hash(hasher), @@ -167,7 +168,7 @@ res } -fn rvalue_eq(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { +fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { let res = match (lhs, rhs) { (Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2), (x, y) => x == y, @@ -176,7 +177,7 @@ res } -fn operand_eq(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { +fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { let res = match (lhs, rhs) { ( Operand::Constant(box Constant { user_ty: _, literal, span: _ }), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/dest_prop.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/dest_prop.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/dest_prop.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/dest_prop.rs 2022-02-23 04:07:21.000000000 +0000 @@ -124,18 +124,15 @@ pub struct DestinationPropagation; impl<'tcx> MirPass<'tcx> for DestinationPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // FIXME(#79191, #82678) - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } - + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // FIXME(#79191, #82678): This is unsound. + // // Only run at mir-opt-level=3 or higher for now (we don't fix up debuginfo and remove // storage statements at the moment). - if tcx.sess.mir_opt_level() < 3 { - return; - } + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let candidates = find_candidates(tcx, body); @@ -244,7 +241,7 @@ kill: BitSet, } -impl Replacements<'tcx> { +impl<'tcx> Replacements<'tcx> { fn new(locals: usize) -> Self { Self { map: IndexVec::from_elem_n(None, locals), kill: BitSet::new_empty(locals) } } @@ -301,7 +298,7 @@ } impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -316,28 +313,6 @@ } } - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - match elem { - PlaceElem::Index(local) => { - if let Some(replacement) = self.replacements.for_src(local) { - bug!( - "cannot replace {:?} with {:?} in index projection {:?}", - local, - replacement, - elem, - ); - } else { - None - } - } - _ => None, - } - } - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { if let Some(replacement) = self.replacements.for_src(place.local) { // Rebase `place`s projections onto `replacement`'s. @@ -397,7 +372,7 @@ unified_locals: InPlaceUnificationTable, } -impl Conflicts<'a> { +impl<'a> Conflicts<'a> { fn build<'tcx>( tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, @@ -646,6 +621,7 @@ options: _, line_spans: _, destination: _, + cleanup: _, } => { // The intended semantics here aren't documented, we just assume that nothing that // could be written to by the assembly may overlap with any other operands. @@ -844,10 +820,7 @@ /// comment) and also throw out assignments that involve a local that has its address taken or is /// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate /// arbitrary places into array indices). -fn find_candidates<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, -) -> Vec> { +fn find_candidates<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Vec> { let mut visitor = FindAssignments { tcx, body, @@ -867,7 +840,7 @@ locals_used_as_array_index: BitSet, } -impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { if let StatementKind::Assign(box ( dest, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/early_otherwise_branch.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/early_otherwise_branch.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/early_otherwise_branch.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/early_otherwise_branch.rs 2022-02-23 04:07:21.000000000 +0000 @@ -25,16 +25,14 @@ pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // FIXME(#78496) - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 + } - if tcx.sess.mir_opt_level() < 3 { - return; - } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running EarlyOtherwiseBranch on {:?}", body.source); + // we are only interested in this bb if the terminator is a switchInt let bbs_with_switch = body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator())); @@ -169,7 +167,7 @@ } } -fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool { +fn is_switch(terminator: &Terminator<'_>) -> bool { matches!(terminator.kind, TerminatorKind::SwitchInt { .. }) } @@ -210,7 +208,7 @@ second_switch_info: SwitchDiscriminantInfo<'tcx>, } -impl<'a, 'tcx> Helper<'a, 'tcx> { +impl<'tcx> Helper<'_, 'tcx> { pub fn go( &self, bb: &BasicBlockData<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/elaborate_drops.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/elaborate_drops.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/elaborate_drops.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/elaborate_drops.rs 2022-02-23 04:07:21.000000000 +0000 @@ -19,6 +19,10 @@ pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { + fn phase_change(&self) -> Option { + Some(MirPhase::DropLowering) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); @@ -145,13 +149,13 @@ ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, } -impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> { +impl fmt::Debug for Elaborator<'_, '_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { +impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { @@ -312,12 +316,12 @@ LookupResult::Parent(Some(parent)) => { let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); if maybe_dead { - span_bug!( + self.tcx.sess.delay_span_bug( terminator.source_info.span, - "drop of untracked, uninitialized value {:?}, place {:?} ({:?})", - bb, - place, - path + &format!( + "drop of untracked, uninitialized value {:?}, place {:?} ({:?})", + bb, place, path, + ), ); } continue; @@ -364,10 +368,9 @@ bb, ), LookupResult::Parent(..) => { - span_bug!( + self.tcx.sess.delay_span_bug( terminator.source_info.span, - "drop of untracked value {:?}", - bb + &format!("drop of untracked value {:?}", bb), ); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/function_item_references.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/function_item_references.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/function_item_references.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/function_item_references.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,12 +11,12 @@ use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; -use crate::MirPass; +use crate::MirLint; pub struct FunctionItemReferences; -impl<'tcx> MirPass<'tcx> for FunctionItemReferences { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for FunctionItemReferences { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = FunctionItemRefChecker { tcx, body }; checker.visit_body(&body); } @@ -27,7 +27,7 @@ body: &'a Body<'tcx>, } -impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { /// Emits a lint for function reference arguments bound by `fmt::Pointer` or passed to /// `transmute`. This only handles arguments in calls outside macro expansions to avoid double /// counting function references formatted as pointers by macros. @@ -92,7 +92,7 @@ } } -impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> { +impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { /// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the /// function defined by `def_id` with the substitutions `substs_ref`. fn check_bound_args( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/generator.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/generator.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/generator.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/generator.rs 2022-02-23 04:07:21.000000000 +0000 @@ -233,7 +233,7 @@ new_ret_local: Local, } -impl TransformVisitor<'tcx> { +impl<'tcx> TransformVisitor<'tcx> { // Make a GeneratorState variant assignment. `core::ops::GeneratorState` only has single // element tuple variants, so we can just write to the downcasted first field and then set the // discriminant to the appropriate variant. @@ -243,7 +243,7 @@ val: Operand<'tcx>, source_info: SourceInfo, ) -> impl Iterator> { - let kind = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None); + let kind = AggregateKind::Adt(self.state_adt_ref.did, idx, self.state_substs, None, None); assert_eq!(self.state_adt_ref.variants[idx].fields.len(), 1); let ty = self .tcx @@ -295,7 +295,7 @@ } } -impl MutVisitor<'tcx> for TransformVisitor<'tcx> { +impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -446,7 +446,7 @@ storage_liveness: IndexVec>>, } -fn locals_live_across_suspend_points( +fn locals_live_across_suspend_points<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, always_live_locals: &storage::AlwaysLiveLocals, @@ -613,7 +613,7 @@ /// time. Generates a bitset for every local of all the other locals that may be /// StorageLive simultaneously with that local. This is used in the layout /// computation; see `GeneratorLayout` for more. -fn compute_storage_conflicts( +fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, saved_locals: &GeneratorSavedLocals, always_live_locals: storage::AlwaysLiveLocals, @@ -672,7 +672,9 @@ local_conflicts: BitMatrix, } -impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> { +impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> + for StorageConflictVisitor<'mir, 'tcx, '_> +{ type FlowState = BitSet; fn visit_statement_before_primary_effect( @@ -694,7 +696,7 @@ } } -impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> { +impl StorageConflictVisitor<'_, '_, '_> { fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. if self.body.basic_blocks()[loc.block].terminator().kind == TerminatorKind::Unreachable { @@ -1232,6 +1234,10 @@ } impl<'tcx> MirPass<'tcx> for StateTransform { + fn phase_change(&self) -> Option { + Some(MirPhase::GeneratorLowering) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty() { yield_ty @@ -1394,7 +1400,7 @@ self.saved_locals.get(place.local) } - fn check_assigned_place(&mut self, place: Place<'tcx>, f: impl FnOnce(&mut Self)) { + fn check_assigned_place(&mut self, place: Place<'_>, f: impl FnOnce(&mut Self)) { if let Some(assigned_local) = self.saved_local_for_direct_place(place) { assert!(self.assigned_local.is_none(), "`check_assigned_place` must not recurse"); @@ -1405,7 +1411,7 @@ } } -impl Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { +impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { let lhs = match self.assigned_local { Some(l) => l, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline/cycle.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline/cycle.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline/cycle.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline/cycle.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking // this query riddiculously often. #[instrument(level = "debug", skip(tcx, root, target))] -crate fn mir_callgraph_reachable( +crate fn mir_callgraph_reachable<'tcx>( tcx: TyCtxt<'tcx>, (root, target): (ty::Instance<'tcx>, LocalDefId), ) -> bool { @@ -33,7 +33,7 @@ level = "debug", skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit) )] - fn process( + fn process<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, caller: ty::Instance<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/inline.rs 2022-02-23 04:07:21.000000000 +0000 @@ -37,21 +37,16 @@ source_info: SourceInfo, } -/// Returns true if MIR inlining is enabled in the current compilation session. -crate fn is_enabled(tcx: TyCtxt<'_>) -> bool { - if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir { - return enabled; - } - - tcx.sess.mir_opt_level() >= 3 -} - impl<'tcx> MirPass<'tcx> for Inline { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !is_enabled(tcx) { - return; + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + if let Some(enabled) = sess.opts.debugging_opts.inline_mir { + return enabled; } + sess.opts.mir_opt_level() >= 3 + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let span = trace_span!("inline", body = %tcx.def_path_str(body.source.def_id())); let _guard = span.enter(); if inline(tcx, body) { @@ -62,7 +57,7 @@ } } -fn inline(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { +fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let def_id = body.source.def_id(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); @@ -73,6 +68,12 @@ if body.source.promoted.is_some() { return false; } + // Avoid inlining into generators, since their `optimized_mir` is used for layout computation, + // which can create a cycle, even when no attempt is made to inline the function in the other + // direction. + if body.generator.is_some() { + return false; + } let mut this = Inliner { tcx, @@ -100,7 +101,7 @@ changed: bool, } -impl Inliner<'tcx> { +impl<'tcx> Inliner<'tcx> { fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range) { for bb in blocks { let bb_data = &caller_body[bb]; @@ -207,19 +208,12 @@ if let Some(callee_def_id) = callee.def_id().as_local() { let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); - // Avoid inlining into generators, - // since their `optimized_mir` is used for layout computation, which can - // create a cycle, even when no attempt is made to inline the function - // in the other direction. - if caller_body.generator.is_some() { - return Err("local generator (query cycle avoidance)"); - } - // Avoid a cycle here by only using `instance_mir` only if we have // a lower `HirId` than the callee. This ensures that the callee will // not inline us. This trick only works without incremental compilation. // So don't do it if that is enabled. - if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id < callee_hir_id { + if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id.index() < callee_hir_id.index() + { return Ok(()); } @@ -441,6 +435,13 @@ } } TerminatorKind::Resume => cost += RESUME_PENALTY, + TerminatorKind::InlineAsm { cleanup, .. } => { + cost += INSTR_COST; + + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; + } + } _ => cost += INSTR_COST, } @@ -784,7 +785,7 @@ always_live_locals: BitSet, } -impl<'a, 'tcx> Integrator<'a, 'tcx> { +impl Integrator<'_, '_> { fn map_local(&self, local: Local) -> Local { let new = if local == RETURN_PLACE { self.destination.local @@ -813,7 +814,7 @@ } } -impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -954,9 +955,13 @@ { bug!("False unwinds should have been removed before inlining") } - TerminatorKind::InlineAsm { ref mut destination, .. } => { + TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => { if let Some(ref mut tgt) = *destination { *tgt = self.map_block(*tgt); + } else if !self.in_cleanup_block { + // Unless this inline asm is in a cleanup block, add an unwind edge to + // the original call's cleanup block + *cleanup = self.cleanup_block; } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/instcombine.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/instcombine.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/instcombine.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/instcombine.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,6 +11,10 @@ pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let ctx = InstCombineContext { tcx, local_decls }; @@ -34,7 +38,7 @@ local_decls: &'a LocalDecls<'tcx>, } -impl<'tcx, 'a> InstCombineContext<'tcx, 'a> { +impl<'tcx> InstCombineContext<'tcx, '_> { fn should_combine(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { self.tcx.consider_optimizing(|| { format!("InstCombine - Rvalue: {:?} SourceInfo: {:?}", rvalue, source_info) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,8 +1,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] @@ -27,11 +25,16 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; -use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted}; +use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; +#[macro_use] +mod pass_manager; + +use pass_manager::{self as pm, Lint, MirLint, WithMinOptLevel}; + mod abort_unwinding_calls; mod add_call_guards; mod add_moves_for_packed_drops; @@ -56,12 +59,15 @@ mod instcombine; mod lower_intrinsics; mod lower_slice_len; +mod marker; mod match_branches; mod multiple_return_terminators; mod normalize_array_len; mod nrvo; +mod remove_false_edges; mod remove_noop_landing_pads; mod remove_storage_markers; +mod remove_uninit_drops; mod remove_unneeded_drops; mod remove_zsts; mod required_consts; @@ -75,10 +81,9 @@ mod uninhabited_enum_branching; mod unreachable_prop; -use rustc_const_eval::transform::check_consts; +use rustc_const_eval::transform::check_consts::{self, ConstCx}; use rustc_const_eval::transform::promote_consts; use rustc_const_eval::transform::validate; -pub use rustc_const_eval::transform::MirPass; use rustc_mir_dataflow::rustc_peek; pub fn provide(providers: &mut Providers) { @@ -143,7 +148,7 @@ tcx: TyCtxt<'tcx>, set: &'a mut FxHashSet, } - impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> { + impl<'tcx> Visitor<'tcx> for GatherCtors<'_, 'tcx> { fn visit_variant_data( &mut self, v: &'tcx hir::VariantData<'tcx>, @@ -167,66 +172,6 @@ set } -fn run_passes( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - mir_phase: MirPhase, - passes: &[&[&dyn MirPass<'tcx>]], -) { - let phase_index = mir_phase.phase_index(); - let validate = tcx.sess.opts.debugging_opts.validate_mir; - - if body.phase >= mir_phase { - return; - } - - if validate { - validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } - - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass<'tcx>| { - let run_hooks = |body: &_, index, is_after| { - let disambiguator = if is_after { "after" } else { "before" }; - dump_mir( - tcx, - Some(&format_args!("{:03}-{:03}", phase_index, index)), - &pass.name(), - &disambiguator, - body, - |_, _| Ok(()), - ); - }; - run_hooks(body, index, false); - pass.run_pass(tcx, body); - run_hooks(body, index, true); - - if validate { - validate::Validator { - when: format!("after {} in phase {:?}", pass.name(), mir_phase), - mir_phase, - } - .run_pass(tcx, body); - } - - index += 1; - }; - - for pass_group in passes { - for pass in *pass_group { - run_pass(*pass); - } - } - - body.phase = mir_phase; - - if mir_phase == MirPhase::Optimization { - validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } -} - fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> ConstQualifs { let const_kind = tcx.hir().body_const_context(def.did); @@ -278,25 +223,25 @@ rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); - run_passes( + pm::run_passes( tcx, &mut body, - MirPhase::Const, - &[&[ + &[ // MIR-level lints. - &check_packed_ref::CheckPackedRef, - &check_const_item_mutation::CheckConstItemMutation, - &function_item_references::FunctionItemReferences, + &Lint(check_packed_ref::CheckPackedRef), + &Lint(check_const_item_mutation::CheckConstItemMutation), + &Lint(function_item_references::FunctionItemReferences), // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), - &rustc_peek::SanityCheck, - ]], + &rustc_peek::SanityCheck, // Just a lint + &marker::PhaseChange(MirPhase::Const), + ], ); tcx.alloc_steal_mir(body) } /// Compute the main MIR body and the list of MIR bodies of the promoteds. -fn mir_promoted( +fn mir_promoted<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, ) -> (&'tcx Steal>, &'tcx Steal>>) { @@ -317,17 +262,17 @@ } body.required_consts = required_consts; + // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); - let promote: &[&dyn MirPass<'tcx>] = &[ - // What we need to run borrowck etc. - &promote_pass, - &simplify::SimplifyCfg::new("promote-consts"), - ]; - - let opt_coverage: &[&dyn MirPass<'tcx>] = - if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] }; - - run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); + pm::run_passes( + tcx, + &mut body, + &[ + &promote_pass, + &simplify::SimplifyCfg::new("promote-consts"), + &coverage::InstrumentCoverage, + ], + ); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) @@ -389,19 +334,10 @@ // Technically we want to not run on regular const items, but oli-obk doesn't know how to // conveniently detect that at this point without looking at the HIR. hir::ConstContext::Const => { - #[rustfmt::skip] - let optimizations: &[&dyn MirPass<'_>] = &[ - &const_prop::ConstProp, - ]; - - #[rustfmt::skip] - run_passes( + pm::run_passes( tcx, &mut body, - MirPhase::Optimization, - &[ - optimizations, - ], + &[&const_prop::ConstProp, &marker::PhaseChange(MirPhase::Optimization)], ); } } @@ -437,7 +373,7 @@ let def = ty::WithOptConstParam::unknown(did); // Do not compute the mir call graph without said call graph actually being used. - if inline::is_enabled(tcx) { + if inline::Inline.is_enabled(&tcx.sess) { let _ = tcx.mir_inliner_callees(ty::InstanceDef::Item(def)); } } @@ -445,8 +381,24 @@ let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); + // IMPORTANT + pm::run_passes(tcx, &mut body, &[&remove_false_edges::RemoveFalseEdges]); + + // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled. + if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) { + pm::run_passes( + tcx, + &mut body, + &[ + &simplify::SimplifyCfg::new("remove-false-edges"), + &remove_uninit_drops::RemoveUninitDrops, + ], + ); + check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint + } + run_post_borrowck_cleanup_passes(tcx, &mut body); - check_consts::post_drop_elaboration::check_live_drops(tcx, &body); + assert!(body.phase == MirPhase::DropLowering); tcx.alloc_steal_mir(body) } @@ -456,7 +408,7 @@ let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ // Remove all things only needed by analysis - &simplify_branches::SimplifyBranches::new("initial"), + &simplify_branches::SimplifyConstCondition::new("initial"), &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), @@ -480,95 +432,72 @@ &deaggregator::Deaggregator, ]; - run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]); + pm::run_passes(tcx, body, post_borrowck_cleanup); } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mir_opt_level = tcx.sess.mir_opt_level(); + fn o1(x: T) -> WithMinOptLevel { + WithMinOptLevel(1, x) + } // Lowering generator control-flow and variables has to happen before we do anything else // to them. We run some optimizations before that, because they may be harder to do on the state // machine than on MIR with async primitives. - let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ - &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. - &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first - &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering - &unreachable_prop::UnreachablePropagation, - &uninhabited_enum_branching::UninhabitedEnumBranching, - &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), - &inline::Inline, - &generator::StateTransform, - ]; - - // Even if we don't do optimizations, we still have to lower generators for codegen. - let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform]; - - // The main optimizations that we do on MIR. - let optimizations: &[&dyn MirPass<'tcx>] = &[ - &remove_storage_markers::RemoveStorageMarkers, - &remove_zsts::RemoveZsts, - &const_goto::ConstGoto, - &remove_unneeded_drops::RemoveUnneededDrops, - &match_branches::MatchBranchSimplification, - // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) - &multiple_return_terminators::MultipleReturnTerminators, - &instcombine::InstCombine, - &separate_const_switch::SeparateConstSwitch, - &const_prop::ConstProp, - &simplify_branches::SimplifyBranches::new("after-const-prop"), - &early_otherwise_branch::EarlyOtherwiseBranch, - &simplify_comparison_integral::SimplifyComparisonIntegral, - &simplify_try::SimplifyArmIdentity, - &simplify_try::SimplifyBranchSame, - &dest_prop::DestinationPropagation, - &simplify_branches::SimplifyBranches::new("final"), - &remove_noop_landing_pads::RemoveNoopLandingPads, - &simplify::SimplifyCfg::new("final"), - &nrvo::RenameReturnPlace, - &const_debuginfo::ConstDebugInfo, - &simplify::SimplifyLocals, - &multiple_return_terminators::MultipleReturnTerminators, - &deduplicate_blocks::DeduplicateBlocks, - ]; - - // Optimizations to run even if mir optimizations have been disabled. - let no_optimizations: &[&dyn MirPass<'tcx>] = &[ - // FIXME(#70073): This pass is responsible for both optimization as well as some lints. - &const_prop::ConstProp, - ]; - - // Some cleanup necessary at least for LLVM and potentially other codegen backends. - let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[ - &add_call_guards::CriticalCallEdges, - // Dump the end result for testing and debugging purposes. - &dump_mir::Marker("PreCodegen"), - ]; - - // End of pass declarations, now actually run the passes. - // Generator Lowering - #[rustfmt::skip] - run_passes( + pm::run_passes( tcx, body, - MirPhase::GeneratorLowering, &[ - if mir_opt_level > 0 { - optimizations_with_generators - } else { - no_optimizations_with_generators - } + &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. + &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first + &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering + &unreachable_prop::UnreachablePropagation, + &uninhabited_enum_branching::UninhabitedEnumBranching, + &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")), + &inline::Inline, + &generator::StateTransform, ], ); - // Main optimization passes - #[rustfmt::skip] - run_passes( + assert!(body.phase == MirPhase::GeneratorLowering); + + // The main optimizations that we do on MIR. + pm::run_passes( tcx, body, - MirPhase::Optimization, &[ - if mir_opt_level > 0 { optimizations } else { no_optimizations }, - pre_codegen_cleanup, + &remove_storage_markers::RemoveStorageMarkers, + &remove_zsts::RemoveZsts, + &const_goto::ConstGoto, + &remove_unneeded_drops::RemoveUnneededDrops, + &match_branches::MatchBranchSimplification, + // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) + &multiple_return_terminators::MultipleReturnTerminators, + &instcombine::InstCombine, + &separate_const_switch::SeparateConstSwitch, + // + // FIXME(#70073): This pass is responsible for both optimization as well as some lints. + &const_prop::ConstProp, + // + // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0. + &o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")), + &early_otherwise_branch::EarlyOtherwiseBranch, + &simplify_comparison_integral::SimplifyComparisonIntegral, + &simplify_try::SimplifyArmIdentity, + &simplify_try::SimplifyBranchSame, + &dest_prop::DestinationPropagation, + &o1(simplify_branches::SimplifyConstCondition::new("final")), + &o1(remove_noop_landing_pads::RemoveNoopLandingPads), + &o1(simplify::SimplifyCfg::new("final")), + &nrvo::RenameReturnPlace, + &const_debuginfo::ConstDebugInfo, + &simplify::SimplifyLocals, + &multiple_return_terminators::MultipleReturnTerminators, + &deduplicate_blocks::DeduplicateBlocks, + // Some cleanup necessary at least for LLVM and potentially other codegen backends. + &add_call_guards::CriticalCallEdges, + &marker::PhaseChange(MirPhase::Optimization), + // Dump the end result for testing and debugging purposes. + &dump_mir::Marker("PreCodegen"), ], ); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_intrinsics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_intrinsics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_intrinsics.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_intrinsics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -135,7 +135,7 @@ } } -fn resolve_rust_intrinsic( +fn resolve_rust_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>, ) -> Option<(Symbol, SubstsRef<'tcx>)> { @@ -148,7 +148,7 @@ None } -fn validate_simd_shuffle(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { +fn validate_simd_shuffle<'tcx>(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { match &args[2] { Operand::Constant(_) => {} // all good _ => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_slice_len.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_slice_len.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_slice_len.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/lower_slice_len.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,6 +10,10 @@ pub struct LowerSliceLenCalls; impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { lower_slice_len_calls(tcx, body) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/marker.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/marker.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/marker.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/marker.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,20 @@ +use std::borrow::Cow; + +use crate::MirPass; +use rustc_middle::mir::{Body, MirPhase}; +use rustc_middle::ty::TyCtxt; + +/// Changes the MIR phase without changing the MIR itself. +pub struct PhaseChange(pub MirPhase); + +impl<'tcx> MirPass<'tcx> for PhaseChange { + fn phase_change(&self) -> Option { + Some(self.0) + } + + fn name(&self) -> Cow<'_, str> { + Cow::from(format!("PhaseChange-{:?}", self.0)) + } + + fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/match_branches.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/match_branches.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/match_branches.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/match_branches.rs 2022-02-23 04:07:21.000000000 +0000 @@ -40,11 +40,11 @@ /// ``` impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 3 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 3 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let param_env = tcx.param_env(def_id); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/multiple_return_terminators.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/multiple_return_terminators.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/multiple_return_terminators.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/multiple_return_terminators.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,11 +9,11 @@ pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); let def_id = body.source.def_id(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/normalize_array_len.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/normalize_array_len.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/normalize_array_len.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/normalize_array_len.rs 2022-02-23 04:07:21.000000000 +0000 @@ -14,11 +14,11 @@ pub struct NormalizeArrayLen; impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // early returns for edge cases of highly unrolled functions if body.basic_blocks().len() > MAX_NUM_BLOCKS { return; @@ -85,7 +85,7 @@ statement_idx: usize, } -impl<'a, 'tcx> Patcher<'a, 'tcx> { +impl<'tcx> Patcher<'_, 'tcx> { fn patch_expand_statement( &mut self, statement: &mut Statement<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/nrvo.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/nrvo.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/nrvo.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/nrvo.rs 2022-02-23 04:07:21.000000000 +0000 @@ -33,11 +33,11 @@ pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - if tcx.sess.mir_opt_level() == 0 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { let def_id = body.source.def_id(); let returned_local = match local_eligible_for_nrvo(body) { Some(l) => l, @@ -165,7 +165,7 @@ } /// Replaces all uses of `self.to_rename` with `_0`. -impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { +impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -221,7 +221,7 @@ } } -impl Visitor<'tcx> for IsReturnPlaceRead { +impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead { fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) { if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() { self.0 = true; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/pass_manager.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/pass_manager.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/pass_manager.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/pass_manager.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,144 @@ +use std::borrow::Cow; + +use rustc_middle::mir::{self, Body, MirPhase}; +use rustc_middle::ty::TyCtxt; +use rustc_session::Session; + +use crate::{validate, MirPass}; + +/// Just like `MirPass`, except it cannot mutate `Body`. +pub trait MirLint<'tcx> { + fn name(&self) -> Cow<'_, str> { + let name = std::any::type_name::(); + if let Some(tail) = name.rfind(':') { + Cow::from(&name[tail + 1..]) + } else { + Cow::from(name) + } + } + + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>); +} + +/// An adapter for `MirLint`s that implements `MirPass`. +#[derive(Debug, Clone)] +pub struct Lint(pub T); + +impl<'tcx, T> MirPass<'tcx> for Lint +where + T: MirLint<'tcx>, +{ + fn name(&self) -> Cow<'_, str> { + self.0.name() + } + + fn is_enabled(&self, sess: &Session) -> bool { + self.0.is_enabled(sess) + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + self.0.run_lint(tcx, body) + } + + fn is_mir_dump_enabled(&self) -> bool { + false + } +} + +pub struct WithMinOptLevel(pub u32, pub T); + +impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel +where + T: MirPass<'tcx>, +{ + fn name(&self) -> Cow<'_, str> { + self.1.name() + } + + fn is_enabled(&self, sess: &Session) -> bool { + sess.mir_opt_level() >= self.0 as usize + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + self.1.run_pass(tcx, body) + } + + fn phase_change(&self) -> Option { + self.1.phase_change() + } +} + +pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) { + let start_phase = body.phase; + let mut cnt = 0; + + let validate = tcx.sess.opts.debugging_opts.validate_mir; + + if validate { + validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase)); + } + + for pass in passes { + if !pass.is_enabled(&tcx.sess) { + continue; + } + + let name = pass.name(); + let dump_enabled = pass.is_mir_dump_enabled(); + + if dump_enabled { + dump_mir(tcx, body, start_phase, &name, cnt, false); + } + + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir(tcx, body, start_phase, &name, cnt, true); + cnt += 1; + } + + if let Some(new_phase) = pass.phase_change() { + if body.phase >= new_phase { + panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); + } + + body.phase = new_phase; + } + + if validate { + validate_body(tcx, body, format!("after pass {}", pass.name())); + } + } + + if validate || body.phase == MirPhase::Optimization { + validate_body(tcx, body, format!("end of phase transition to {:?}", body.phase)); + } +} + +pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { + validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); +} + +pub fn dump_mir<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + phase: MirPhase, + pass_name: &str, + cnt: usize, + is_after: bool, +) { + let phase_index = phase as u32; + + mir::dump_mir( + tcx, + Some(&format_args!("{:03}-{:03}", phase_index, cnt)), + pass_name, + if is_after { &"after" } else { &"before" }, + body, + |_, _| Ok(()), + ); +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_false_edges.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_false_edges.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_false_edges.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_false_edges.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,29 @@ +use rustc_middle::mir::{Body, TerminatorKind}; +use rustc_middle::ty::TyCtxt; + +use crate::MirPass; + +/// Removes `FalseEdge` and `FalseUnwind` terminators from the MIR. +/// +/// These are only needed for borrow checking, and can be removed afterwards. +/// +/// FIXME: This should probably have its own MIR phase. +pub struct RemoveFalseEdges; + +impl<'tcx> MirPass<'tcx> for RemoveFalseEdges { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + for block in body.basic_blocks_mut() { + let terminator = block.terminator_mut(); + terminator.kind = match terminator.kind { + TerminatorKind::FalseEdge { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + TerminatorKind::FalseUnwind { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + + _ => continue, + } + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,18 +10,14 @@ /// code for these. pub struct RemoveNoopLandingPads; -pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.panic_strategy() == PanicStrategy::Abort { - return; +impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.panic_strategy() != PanicStrategy::Abort } - debug!("remove_noop_landing_pads({:?})", body); - - RemoveNoopLandingPads.remove_nop_landing_pads(body) -} -impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - remove_noop_landing_pads(tcx, body); + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!("remove_noop_landing_pads({:?})", body); + self.remove_nop_landing_pads(body) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_storage_markers.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_storage_markers.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_storage_markers.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_storage_markers.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,10 @@ pub struct RemoveStorageMarkers; impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.emit_lifetime_markers() { return; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_uninit_drops.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_uninit_drops.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_uninit_drops.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_uninit_drops.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,171 @@ +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv}; + +use crate::MirPass; + +/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at +/// that point. +/// +/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and +/// running const-checking after drop elaboration makes it opimization dependent, causing issues +/// like [#90770]. +/// +/// [#90770]: https://github.com/rust-lang/rust/issues/90770 +pub struct RemoveUninitDrops; + +impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); + let Ok(move_data) = MoveData::gather_moves(body, tcx, param_env) else { + // We could continue if there are move errors, but there's not much point since our + // init data isn't complete. + return; + }; + + let mdpe = MoveDataParamEnv { move_data, param_env }; + let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) + .pass_name("remove_uninit_drops") + .iterate_to_fixpoint() + .into_results_cursor(body); + + let mut to_remove = vec![]; + for (bb, block) in body.basic_blocks().iter_enumerated() { + let terminator = block.terminator(); + let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) + = &terminator.kind + else { continue }; + + maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); + + // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone. + let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else { + continue; + }; + + let should_keep = is_needs_drop_and_init( + tcx, + param_env, + maybe_inits.get(), + &mdpe.move_data, + place.ty(body, tcx).ty, + mpi, + ); + if !should_keep { + to_remove.push(bb) + } + } + + for bb in to_remove { + let block = &mut body.basic_blocks_mut()[bb]; + + let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + = &block.terminator().kind + else { unreachable!() }; + + // Replace block terminator with `Goto`. + let target = *target; + let old_terminator_kind = std::mem::replace( + &mut block.terminator_mut().kind, + TerminatorKind::Goto { target }, + ); + + // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. + if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { + block.statements.push(Statement { + source_info: block.terminator().source_info, + kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), + }); + } + } + } +} + +fn is_needs_drop_and_init<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + maybe_inits: &BitSet, + move_data: &MoveData<'tcx>, + ty: Ty<'tcx>, + mpi: MovePathIndex, +) -> bool { + // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl. + if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) { + return false; + } + + let field_needs_drop_and_init = |(f, f_ty, mpi)| { + let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f)); + let Some(mpi) = child else { + return f_ty.needs_drop(tcx, param_env); + }; + + is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi) + }; + + // This pass is only needed for const-checking, so it doesn't handle as many cases as + // `DropCtxt::open_drop`, since they aren't relevant in a const-context. + match ty.kind() { + ty::Adt(adt, substs) => { + let dont_elaborate = adt.is_union() || adt.is_manually_drop() || adt.has_dtor(tcx); + if dont_elaborate { + return true; + } + + // Look at all our fields, or if we are an enum all our variants and their fields. + // + // If a field's projection *is not* present in `MoveData`, it has the same + // initializedness as its parent (maybe init). + // + // If its projection *is* present in `MoveData`, then the field may have been moved + // from separate from its parent. Recurse. + adt.variants.iter_enumerated().any(|(vid, variant)| { + // Enums have multiple variants, which are discriminated with a `Downcast` projection. + // Structs have a single variant, and don't use a `Downcast` projection. + let mpi = if adt.is_enum() { + let downcast = + move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); + let Some(dc_mpi) = downcast else { + return variant_needs_drop(tcx, param_env, substs, variant); + }; + + dc_mpi + } else { + mpi + }; + + variant + .fields + .iter() + .enumerate() + .map(|(f, field)| (Field::from_usize(f), field.ty(tcx, substs), mpi)) + .any(field_needs_drop_and_init) + }) + } + + ty::Tuple(_) => ty + .tuple_fields() + .enumerate() + .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) + .any(field_needs_drop_and_init), + + _ => true, + } +} + +fn variant_needs_drop<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + substs: SubstsRef<'tcx>, + variant: &VariantDef, +) -> bool { + variant.fields.iter().any(|field| { + let f_ty = field.ty(tcx, substs); + f_ty.needs_drop(tcx, param_env) + }) +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,8 @@ -//! This pass replaces a drop of a type that does not need dropping, with a goto +//! This pass replaces a drop of a type that does not need dropping, with a goto. +//! +//! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is +//! useful because (unlike MIR building) it runs after type checking, so it can make use of +//! `Reveal::All` to provide more precies type information. use crate::MirPass; use rustc_middle::mir::*; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_zsts.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_zsts.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_zsts.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/remove_zsts.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,6 +8,10 @@ pub struct RemoveZsts; impl<'tcx> MirPass<'tcx> for RemoveZsts { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Avoid query cycles (generators require optimized MIR for layout). if tcx.type_of(body.source.def_id()).is_generator() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/required_consts.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/required_consts.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/required_consts.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/required_consts.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ } } -impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { if let Some(ct) = constant.literal.const_for_ty() { if let ConstKind::Unevaluated(_) = ct.val { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/reveal_all.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/reveal_all.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/reveal_all.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/reveal_all.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,15 +8,18 @@ pub struct RevealAll; impl<'tcx> MirPass<'tcx> for RevealAll { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.mir_opt_level() >= 3 || super::inline::Inline.is_enabled(sess) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // This pass must run before inlining, since we insert callee bodies in RevealAll mode. // Do not apply this transformation to generators. - if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx)) - && body.generator.is_none() - { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - RevealAllVisitor { tcx, param_env }.visit_body(body); + if body.generator.is_some() { + return; } + + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + RevealAllVisitor { tcx, param_env }.visit_body(body); } } @@ -33,26 +36,9 @@ #[inline] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { - *ty = self.tcx.normalize_erasing_regions(self.param_env, ty); - } - - #[inline] - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - match elem { - PlaceElem::Field(field, ty) => { - let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty); - if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } - } - // None of those contain a Ty. - PlaceElem::Index(..) - | PlaceElem::Deref - | PlaceElem::ConstantIndex { .. } - | PlaceElem::Subslice { .. } - | PlaceElem::Downcast(..) => None, - } + // We have to use `try_normalize_erasing_regions` here, since it's + // possible that we visit impossible-to-satisfy where clauses here, + // see #91745 + *ty = self.tcx.try_normalize_erasing_regions(self.param_env, *ty).unwrap_or(ty); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/separate_const_switch.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/separate_const_switch.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/separate_const_switch.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/separate_const_switch.rs 2022-02-23 04:07:21.000000000 +0000 @@ -45,11 +45,11 @@ pub struct SeparateConstSwitch; impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // If execution did something, applying a simplification layer // helps later passes optimize the copy away. if separate_const_switch(body) > 0 { @@ -59,7 +59,7 @@ } /// Returns the amount of blocks that were duplicated -pub fn separate_const_switch<'tcx>(body: &mut Body<'tcx>) -> usize { +pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new(); let predecessors = body.predecessors(); 'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/shim.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/shim.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/shim.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/shim.rs 2022-02-23 04:07:21.000000000 +0000 @@ -17,8 +17,8 @@ use crate::util::expand_aggregate; use crate::{ - abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads, - run_passes, simplify, + abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, marker, pass_manager as pm, + remove_noop_landing_pads, simplify, }; use rustc_middle::mir::patch::MirPatch; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; @@ -64,7 +64,19 @@ build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } - ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), + + ty::InstanceDef::DropGlue(def_id, ty) => { + // FIXME(#91576): Drop shims for generators aren't subject to the MIR passes at the end + // of this function. Is this intentional? + if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(ty::TyS::kind) { + let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap(); + let body = body.clone().subst(tcx, substs); + debug!("make_shim({:?}) = {:?}", instance, body); + return body; + } + + build_drop_shim(tcx, def_id, ty) + } ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) @@ -75,17 +87,17 @@ }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes( + pm::run_passes( tcx, &mut result, - MirPhase::Const, - &[&[ + &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, - ]], + &marker::PhaseChange(MirPhase::Const), + ], ); debug!("make_shim({:?}) = {:?}", instance, result); @@ -132,11 +144,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> Body<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); - // Check if this is a generator, if so, return the drop glue for it - if let Some(&ty::Generator(gen_def_id, substs, _)) = ty.map(|ty| ty.kind()) { - let body = tcx.optimized_mir(gen_def_id).generator_drop().unwrap(); - return body.clone().subst(tcx, substs); - } + assert!(!matches!(ty, Some(ty) if ty.is_generator())); let substs = if let Some(ty) = ty { tcx.intern_substs(&[ty.into()]) @@ -239,7 +247,7 @@ pub param_env: ty::ParamEnv<'tcx>, } -impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> { +impl fmt::Debug for DropShimElaborator<'_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { Ok(()) } @@ -329,7 +337,7 @@ sig: ty::FnSig<'tcx>, } -impl CloneShimBuilder<'tcx> { +impl<'tcx> CloneShimBuilder<'tcx> { fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self { // we must subst the self_ty because it's // otherwise going to be TySelf and we can't index @@ -769,7 +777,7 @@ adt_def.variants[variant_index].fields.iter().enumerate().map(|(idx, field_def)| { (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs)) }), - AggregateKind::Adt(adt_def, variant_index, substs, None, None), + AggregateKind::Adt(adt_def.did, variant_index, substs, None, None), source_info, tcx, ) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_branches.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_branches.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_branches.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_branches.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,22 +1,21 @@ -//! A pass that simplifies branches when their condition is known. - use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use std::borrow::Cow; -pub struct SimplifyBranches { +/// A pass that replaces a branch with a goto when its condition is known. +pub struct SimplifyConstCondition { label: String, } -impl SimplifyBranches { +impl SimplifyConstCondition { pub fn new(label: &str) -> Self { - SimplifyBranches { label: format!("SimplifyBranches-{}", label) } + SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) } } } -impl<'tcx> MirPass<'tcx> for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } @@ -34,15 +33,8 @@ } => { let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); if let Some(constant) = constant { - let otherwise = targets.otherwise(); - let mut ret = TerminatorKind::Goto { target: otherwise }; - for (v, t) in targets.iter() { - if v == constant { - ret = TerminatorKind::Goto { target: t }; - break; - } - } - ret + let target = targets.target_for_value(constant); + TerminatorKind::Goto { target } } else { continue; } @@ -53,12 +45,6 @@ Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, - TerminatorKind::FalseEdge { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } - TerminatorKind::FalseUnwind { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } _ => continue, }; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs 2022-02-23 04:07:21.000000000 +0000 @@ -26,6 +26,10 @@ pub struct SimplifyComparisonIntegral; impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyComparisonIntegral on {:?}", body.source); @@ -144,7 +148,7 @@ body: &'a Body<'tcx>, } -impl<'a, 'tcx> OptimizationFinder<'a, 'tcx> { +impl<'tcx> OptimizationFinder<'_, 'tcx> { fn find_optimizations(&self) -> Vec> { self.body .basic_blocks() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify.rs 2022-02-23 04:07:21.000000000 +0000 @@ -47,7 +47,7 @@ } } -pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { +pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { CfgSimplifier::new(body).simplify(); remove_dead_blocks(tcx, body); @@ -262,7 +262,7 @@ } } -pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { +pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks().len(); if num_blocks == reachable.count() { @@ -368,6 +368,10 @@ pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running SimplifyLocals on {:?}", body.source); simplify_locals(body, tcx); @@ -450,7 +454,7 @@ } /// Updates the use counts to reflect the removal of given statement. - fn statement_removed(&mut self, statement: &Statement<'tcx>) { + fn statement_removed(&mut self, statement: &Statement<'_>) { self.increment = false; // The location of the statement is irrelevant. @@ -459,7 +463,7 @@ } /// Visits a left-hand side of an assignment. - fn visit_lhs(&mut self, place: &Place<'tcx>, location: Location) { + fn visit_lhs(&mut self, place: &Place<'_>, location: Location) { if place.is_indirect() { // A use, not a definition. self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); @@ -476,7 +480,7 @@ } } -impl Visitor<'_> for UsedLocals { +impl<'tcx> Visitor<'tcx> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::LlvmInlineAsm(..) @@ -514,7 +518,7 @@ } /// Removes unused definitions. Updates the used locals to reflect the changes made. -fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) { +fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>) { // The use counts are updated as we remove the statements. A local might become unused // during the retain operation, leading to a temporary inconsistency (storage statements or // definitions referencing the local might remain). For correctness it is crucial that this diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_try.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_try.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_try.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/simplify_try.rs 2022-02-23 04:07:21.000000000 +0000 @@ -102,7 +102,7 @@ type StmtIter<'a, 'tcx> = Peekable>>>; - fn is_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + fn is_storage_stmt(stmt: &Statement<'_>) -> bool { matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_)) } @@ -122,8 +122,8 @@ /// Eats consecutive `StorageLive` and `StorageDead` Statements. /// The iterator `stmt_iter` is not advanced if none were found. - fn try_eat_storage_stmts<'a, 'tcx>( - stmt_iter: &mut StmtIter<'a, 'tcx>, + fn try_eat_storage_stmts( + stmt_iter: &mut StmtIter<'_, '_>, storage_live_stmts: &mut Vec<(usize, Local)>, storage_dead_stmts: &mut Vec<(usize, Local)>, ) { @@ -136,7 +136,7 @@ }) } - fn is_tmp_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + fn is_tmp_storage_stmt(stmt: &Statement<'_>) -> bool { use rustc_middle::mir::StatementKind::Assign; if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = &stmt.kind { place.as_local().is_some() && p.as_local().is_some() @@ -147,8 +147,8 @@ /// Eats consecutive `Assign` Statements. // The iterator `stmt_iter` is not advanced if none were found. - fn try_eat_assign_tmp_stmts<'a, 'tcx>( - stmt_iter: &mut StmtIter<'a, 'tcx>, + fn try_eat_assign_tmp_stmts( + stmt_iter: &mut StmtIter<'_, '_>, tmp_assigns: &mut Vec<(Local, Local)>, nop_stmts: &mut Vec, ) { @@ -163,9 +163,9 @@ }) } - fn find_storage_live_dead_stmts_for_local<'tcx>( + fn find_storage_live_dead_stmts_for_local( local: Local, - stmts: &[Statement<'tcx>], + stmts: &[Statement<'_>], ) -> Option<(usize, usize)> { trace!("looking for {:?}", local); let mut storage_live_stmt = None; @@ -452,14 +452,14 @@ } impl LocalUseCounter { - fn get_local_uses<'tcx>(body: &Body<'tcx>) -> IndexVec { + fn get_local_uses(body: &Body<'_>) -> IndexVec { let mut counter = LocalUseCounter { local_uses: IndexVec::from_elem(0, &body.local_decls) }; counter.visit_body(body); counter.local_uses } } -impl<'tcx> Visitor<'tcx> for LocalUseCounter { +impl Visitor<'_> for LocalUseCounter { fn visit_local(&mut self, local: &Local, context: PlaceContext, _location: Location) { if context.is_storage_marker() || context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) @@ -510,7 +510,7 @@ /// ```rust /// discriminant(_LOCAL_TO_SET) = VAR_IDX; /// ``` -fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> { +fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> { match &stmt.kind { StatementKind::SetDiscriminant { place, variant_index } => { Some((place.as_local()?, *variant_index)) @@ -588,7 +588,7 @@ tcx: TyCtxt<'tcx>, } -impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { +impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> { fn find(&self) -> Vec { self.body .basic_blocks() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs 2022-02-23 04:07:21.000000000 +0000 @@ -70,6 +70,10 @@ } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if body.source.promoted.is_some() { return; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/unreachable_prop.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/unreachable_prop.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/unreachable_prop.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_mir_transform/src/unreachable_prop.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,13 +11,13 @@ pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt - // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt + // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. + sess.mir_opt_level() >= 4 + } + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut unreachable_blocks = FxHashSet::default(); let mut replacements = FxHashMap::default(); @@ -64,7 +64,7 @@ } } -fn remove_successors( +fn remove_successors<'tcx, F>( terminator_kind: &TerminatorKind<'tcx>, predicate: F, ) -> Option> diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/collector.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/collector.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/collector.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/collector.rs 2022-02-23 04:07:21.000000000 +0000 @@ -498,7 +498,7 @@ /// the user's terminal with thousands of lines of type-name. /// /// If the type name is longer than before+after, it will be written to a file. -fn shrunk_instance_name( +fn shrunk_instance_name<'tcx>( tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>, before: usize, @@ -688,15 +688,6 @@ _ => bug!(), } } - mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => { - let tcx = self.tcx; - let exchange_malloc_fn_def_id = - tcx.require_lang_item(LangItem::ExchangeMalloc, None); - let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(self.tcx, instance, span)); - } - } mir::Rvalue::ThreadLocalRef(def_id) => { assert!(self.tcx.is_thread_local_static(def_id)); let instance = Instance::mono(self.tcx, def_id); @@ -1145,7 +1136,7 @@ entry_fn: Option<(DefId, EntryFnType)>, } -impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { +impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> { fn visit_item(&mut self, item: &'v hir::Item<'v>) { match item.kind { hir::ItemKind::ExternCrate(..) @@ -1225,7 +1216,7 @@ fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {} } -impl RootCollector<'_, 'v> { +impl<'v> RootCollector<'_, 'v> { fn is_root(&self, def_id: LocalDefId) -> bool { !item_requires_monomorphization(self.tcx, def_id) && match self.mode { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,6 @@ #![feature(crate_visibility_modifier)] #![feature(control_flow_enum)] #![feature(let_else)] -#![feature(in_band_lifetimes)] #![recursion_limit = "256"] #[macro_use] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/default.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/default.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/default.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/default.rs 2022-02-23 04:07:21.000000000 +0000 @@ -378,7 +378,7 @@ name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } -fn mono_item_linkage_and_visibility( +fn mono_item_linkage_and_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, @@ -393,7 +393,7 @@ type CguNameCache = FxHashMap<(DefId, bool), Symbol>; -fn mono_item_visibility( +fn mono_item_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/merging.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/merging.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/merging.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/merging.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder}; -use rustc_span::symbol::{Symbol, SymbolStr}; +use rustc_span::symbol::Symbol; use super::PartitioningCx; use crate::partitioning::PreInliningPartitioning; @@ -24,11 +24,11 @@ // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str()); + codegen_units.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); // This map keeps track of what got merged into what. - let mut cgu_contents: FxHashMap> = - codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect(); + let mut cgu_contents: FxHashMap> = + codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect(); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > cx.target_cgu_count { @@ -69,7 +69,7 @@ // were actually modified by merging. .filter(|(_, cgu_contents)| cgu_contents.len() > 1) .map(|(current_cgu_name, cgu_contents)| { - let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| &s[..]).collect(); + let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect(); // Sort the names, so things are deterministic and easy to // predict. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/mod.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/partitioning/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -208,7 +208,7 @@ internalization_candidates: _, } = post_inlining; - result.sort_by_cached_key(|cgu| cgu.name().as_str()); + result.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); result } @@ -366,7 +366,7 @@ for cgu in codegen_units { tcx.prof.artifact_size( "codegen_unit_size_estimate", - &cgu.name().as_str()[..], + cgu.name().as_str(), cgu.size_estimate() as u64, ); } @@ -401,7 +401,7 @@ cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push(' '); - output.push_str(&cgu_name.as_str()); + output.push_str(cgu_name.as_str()); let linkage_abbrev = match linkage { Linkage::External => "External", diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/util.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_monomorphize/src/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,7 @@ /// /// During the same compile all closures dump the information in the same file /// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked. -crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { +crate fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { let mut file = if let Ok(file) = OpenOptions::new() .create(true) .append(true) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/lib.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -326,6 +326,12 @@ parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } +pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream { + let source = pprust::crate_to_string_for_macros(krate); + let filename = FileName::macro_expansion_source_code(&source); + parse_stream_from_source_str(filename, source, sess, Some(krate.span)) +} + pub fn parse_cfg_attr( attr: &Attribute, parse_sess: &ParseSess, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/attr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/attr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/attr.rs 2022-01-20 17:48:08.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/attr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,4 @@ -use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Nonterminal}; @@ -177,7 +177,7 @@ AttrWrapper::empty(), true, false, - |_| true, + FnParseMode { req_name: |_| true, req_body: true }, ForceCollect::No, ) { Ok(Some(item)) => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/diagnostics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/diagnostics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/diagnostics.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/diagnostics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,9 @@ +use super::pat::Expected; use super::ty::AllowPlus; -use super::TokenType; -use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType}; +use super::{ + BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep, + TokenExpectType, TokenType, +}; use rustc_ast as ast; use rustc_ast::ptr::P; @@ -19,6 +22,8 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; +use std::mem::take; + use tracing::{debug, trace}; const TURBOFISH_SUGGESTION_STR: &str = @@ -301,7 +306,7 @@ } } - let expect = tokens_to_string(&expected[..]); + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { let short_expect = if expected.len() > 6 { @@ -904,7 +909,7 @@ // So far we have parsed `foo]) -> bool { - if self.eat(&token::Semi) { + if self.token.kind == TokenKind::Semi { + self.bump(); let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`"); err.span_suggestion_short( self.prev_token.span, @@ -2075,4 +2081,177 @@ ); err } + + /// Some special error handling for the "top-level" patterns in a match arm, + /// `for` loop, `let`, &c. (in contrast to subpatterns within such). + crate fn maybe_recover_colon_colon_in_pat_typo( + &mut self, + mut first_pat: P, + ra: RecoverColon, + expected: Expected, + ) -> P { + if RecoverColon::Yes != ra || token::Colon != self.token.kind { + return first_pat; + } + if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) + || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) + { + return first_pat; + } + // The pattern looks like it might be a path with a `::` -> `:` typo: + // `match foo { bar:baz => {} }` + let span = self.token.span; + // We only emit "unexpected `:`" error here if we can successfully parse the + // whole pattern correctly in that case. + let snapshot = self.clone(); + + // Create error for "unexpected `:`". + match self.expected_one_of_not_found(&[], &[]) { + Err(mut err) => { + self.bump(); // Skip the `:`. + match self.parse_pat_no_top_alt(expected) { + Err(mut inner_err) => { + // Carry on as if we had not done anything, callers will emit a + // reasonable error. + inner_err.cancel(); + err.cancel(); + *self = snapshot; + } + Ok(mut pat) => { + // We've parsed the rest of the pattern. + let new_span = first_pat.span.to(pat.span); + let mut show_sugg = false; + // Try to construct a recovered pattern. + match &mut pat.kind { + PatKind::Struct(qself @ None, path, ..) + | PatKind::TupleStruct(qself @ None, path, _) + | PatKind::Path(qself @ None, path) => match &first_pat.kind { + PatKind::Ident(_, ident, _) => { + path.segments.insert(0, PathSegment::from_ident(ident.clone())); + path.span = new_span; + show_sugg = true; + first_pat = pat; + } + PatKind::Path(old_qself, old_path) => { + path.segments = old_path + .segments + .iter() + .cloned() + .chain(take(&mut path.segments)) + .collect(); + path.span = new_span; + *qself = old_qself.clone(); + first_pat = pat; + show_sugg = true; + } + _ => {} + }, + PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { + match &first_pat.kind { + PatKind::Ident(_, old_ident, _) => { + let path = PatKind::Path( + None, + Path { + span: new_span, + segments: vec![ + PathSegment::from_ident(old_ident.clone()), + PathSegment::from_ident(ident.clone()), + ], + tokens: None, + }, + ); + first_pat = self.mk_pat(new_span, path); + show_sugg = true; + } + PatKind::Path(old_qself, old_path) => { + let mut segments = old_path.segments.clone(); + segments.push(PathSegment::from_ident(ident.clone())); + let path = PatKind::Path( + old_qself.clone(), + Path { span: new_span, segments, tokens: None }, + ); + first_pat = self.mk_pat(new_span, path); + show_sugg = true; + } + _ => {} + } + } + _ => {} + } + if show_sugg { + err.span_suggestion( + span, + "maybe write a path separator here", + "::".to_string(), + Applicability::MaybeIncorrect, + ); + } else { + first_pat = self.mk_pat(new_span, PatKind::Wild); + } + err.emit(); + } + } + } + _ => { + // Carry on as if we had not done anything. This should be unreachable. + *self = snapshot; + } + }; + first_pat + } + + /// Some special error handling for the "top-level" patterns in a match arm, + /// `for` loop, `let`, &c. (in contrast to subpatterns within such). + crate fn maybe_recover_unexpected_comma( + &mut self, + lo: Span, + rc: RecoverComma, + ) -> PResult<'a, ()> { + if rc == RecoverComma::No || self.token != token::Comma { + return Ok(()); + } + + // An unexpected comma after a top-level pattern is a clue that the + // user (perhaps more accustomed to some other language) forgot the + // parentheses in what should have been a tuple pattern; return a + // suggestion-enhanced error here rather than choking on the comma later. + let comma_span = self.token.span; + self.bump(); + if let Err(mut err) = self.skip_pat_list() { + // We didn't expect this to work anyway; we just wanted to advance to the + // end of the comma-sequence so we know the span to suggest parenthesizing. + err.cancel(); + } + let seq_span = lo.to(self.prev_token.span); + let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); + if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { + const MSG: &str = "try adding parentheses to match on a tuple..."; + + err.span_suggestion( + seq_span, + MSG, + format!("({})", seq_snippet), + Applicability::MachineApplicable, + ); + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), + Applicability::MachineApplicable, + ); + } + Err(err) + } + + /// Parse and throw away a parenthesized comma separated + /// sequence of patterns until `)` is reached. + fn skip_pat_list(&mut self) -> PResult<'a, ()> { + while !self.check(&token::CloseDelim(token::Paren)) { + self.parse_pat_no_top_alt(None)?; + if !self.eat(&token::Comma) { + return Ok(()); + } + } + Ok(()) + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/expr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/expr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/expr.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/expr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -213,11 +213,11 @@ } } + // Look for JS' `===` and `!==` and recover if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) && self.token.kind == token::Eq && self.prev_token.span.hi() == self.token.span.lo() { - // Look for JS' `===` and `!==` and recover 😇 let sp = op.span.to(self.token.span); let sugg = match op.node { AssocOp::Equal => "==", @@ -235,6 +235,38 @@ self.bump(); } + // Look for PHP's `<>` and recover + if op.node == AssocOp::Less + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<>`") + .span_suggestion_short( + sp, + "`<>` is not a valid comparison operator, use `!=`", + "!=".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + self.bump(); + } + + // Look for C++'s `<=>` and recover + if op.node == AssocOp::LessEqual + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<=>`") + .span_label( + sp, + "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`", + ) + .emit(); + self.bump(); + } + let op = op.node; // Special cases: if op == AssocOp::As { @@ -1100,30 +1132,37 @@ snapshot.bump(); // `(` match snapshot.parse_struct_fields(path, false, token::Paren) { Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => { - // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest + // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. *self = snapshot; let close_paren = self.prev_token.span; let span = lo.to(self.prev_token.span); - err.cancel(); - self.struct_span_err( - span, - "invalid `struct` delimiters or `fn` call arguments", - ) - .multipart_suggestion( - &format!("if `{}` is a struct, use braces as delimiters", name), - vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())], - Applicability::MaybeIncorrect, - ) - .multipart_suggestion( - &format!("if `{}` is a function, use the arguments directly", name), - fields - .into_iter() - .map(|field| (field.span.until(field.expr.span), String::new())) - .collect(), - Applicability::MaybeIncorrect, - ) - .emit(); + if !fields.is_empty() { + err.cancel(); + let mut err = self.struct_span_err( + span, + "invalid `struct` delimiters or `fn` call arguments", + ); + err.multipart_suggestion( + &format!("if `{}` is a struct, use braces as delimiters", name), + vec![ + (open_paren, " { ".to_string()), + (close_paren, " }".to_string()), + ], + Applicability::MaybeIncorrect, + ); + err.multipart_suggestion( + &format!("if `{}` is a function, use the arguments directly", name), + fields + .into_iter() + .map(|field| (field.span.until(field.expr.span), String::new())) + .collect(), + Applicability::MaybeIncorrect, + ); + err.emit(); + } else { + err.emit(); + } return Some(self.mk_expr_err(span)); } Ok(_) => {} @@ -1258,7 +1297,6 @@ } else if self.eat_keyword(kw::Let) { self.parse_let_expr(attrs) } else if self.eat_keyword(kw::Underscore) { - self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces @@ -1601,7 +1639,7 @@ next_token.kind { if self.token.span.hi() == next_token.span.lo() { - let s = String::from("0.") + &symbol.as_str(); + let s = String::from("0.") + symbol.as_str(); let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); return Some(Token::new(kind, self.token.span.to(next_token.span))); } @@ -1672,7 +1710,8 @@ ); } LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); if looks_like_width_suffix(&['i', 'u'], &suf) { // If it looks like a width, try to be helpful. let msg = format!("invalid width `{}` for integer literal", &suf[1..]); @@ -1688,8 +1727,9 @@ } } LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['f'], &suf) { + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); + if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. let msg = format!("invalid width `{}` for float literal", &suf[1..]); self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit(); @@ -1988,25 +2028,34 @@ let lo = self.prev_token.span; let cond = self.parse_cond_expr()?; + let missing_then_block_binop_span = || { + match cond.kind { + ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right) + if let ExprKind::Block(..) = right.kind => Some(binop_span), + _ => None + } + }; + // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then // verify that the last statement is either an implicit return (no `;`) or an explicit // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. - let thn = if self.eat_keyword(kw::Else) || !cond.returns() { - self.error_missing_if_cond(lo, cond.span) + let thn = if self.token.is_keyword(kw::Else) || !cond.returns() { + if let Some(binop_span) = missing_then_block_binop_span() { + self.error_missing_if_then_block(lo, None, Some(binop_span)).emit(); + self.mk_block_err(cond.span) + } else { + self.error_missing_if_cond(lo, cond.span) + } } else { let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery. let not_block = self.token != token::OpenDelim(token::Brace); - let block = self.parse_block().map_err(|mut err| { + let block = self.parse_block().map_err(|err| { if not_block { - err.span_label(lo, "this `if` expression has a condition, but no block"); - if let ExprKind::Binary(_, _, ref right) = cond.kind { - if let ExprKind::Block(_, _) = right.kind { - err.help("maybe you forgot the right operand of the condition?"); - } - } + self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span()) + } else { + err } - err })?; self.error_on_if_block_attrs(lo, false, block.span, &attrs); block @@ -2015,6 +2064,28 @@ Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) } + fn error_missing_if_then_block( + &self, + if_span: Span, + err: Option>, + binop_span: Option, + ) -> DiagnosticBuilder<'a> { + let msg = "this `if` expression has a condition, but no block"; + + let mut err = if let Some(mut err) = err { + err.span_label(if_span, msg); + err + } else { + self.struct_span_err(if_span, msg) + }; + + if let Some(binop_span) = binop_span { + err.span_help(binop_span, "maybe you forgot the right operand of the condition?"); + } + + err + } + fn error_missing_if_cond(&self, lo: Span, span: Span) -> P { let sp = self.sess.source_map().next_point(lo); self.struct_span_err(sp, "missing condition for `if` expression") @@ -2550,7 +2621,6 @@ 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)) { - self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); break; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/generics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/generics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/generics.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/generics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,7 +5,7 @@ self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause, }; use rustc_errors::PResult; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; impl<'a> Parser<'a> { /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. @@ -59,19 +59,8 @@ self.expect(&token::Colon)?; let ty = self.parse_ty()?; - // Parse optional const generics default value, taking care of feature gating the spans - // with the unstable syntax mechanism. - let default = if self.eat(&token::Eq) { - // The gated span goes from the `=` to the end of the const argument that follows (and - // which could be a block expression). - let start = self.prev_token.span; - let const_arg = self.parse_const_arg()?; - let span = start.to(const_arg.value.span); - self.sess.gated_spans.gate(sym::const_generics_defaults, span); - Some(const_arg) - } else { - None - }; + // Parse optional const generics default value. + let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; Ok(GenericParam { ident, @@ -92,6 +81,19 @@ let attrs = self.parse_outer_attributes()?; let param = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + if this.eat_keyword_noexpect(kw::SelfUpper) { + // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing + // as if `Self` never existed. + this.struct_span_err( + this.prev_token.span, + "unexpected keyword `Self` in generic parameters", + ) + .note("you cannot use `Self` as a generic parameter because it is reserved for associated items") + .emit(); + + this.eat(&token::Comma); + } + let param = if this.check_lifetime() { let lifetime = this.expect_lifetime(); // Parse lifetime parameter. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/item.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/item.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/item.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/item.rs 2022-02-23 04:07:21.000000000 +0000 @@ -15,6 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; +use rustc_span::lev_distance::lev_distance; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -26,7 +27,7 @@ /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { let (attrs, items, span) = self.parse_mod(&token::Eof)?; - Ok(ast::Crate { attrs, items, span }) + Ok(ast::Crate { attrs, items, span, id: DUMMY_NODE_ID, is_placeholder: false }) } /// Parses a `mod { ... }` or `mod ;` item. @@ -78,16 +79,17 @@ impl<'a> Parser<'a> { pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { - self.parse_item_(|_| true, force_collect).map(|i| i.map(P)) + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P)) } fn parse_item_( &mut self, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; - self.parse_item_common(attrs, true, false, req_name, force_collect) + self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) } pub(super) fn parse_item_common( @@ -95,7 +97,7 @@ attrs: AttrWrapper, mac_allowed: bool, attrs_allowed: bool, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { // Don't use `maybe_whole` so that we have precise control @@ -113,7 +115,8 @@ let mut unclosed_delims = vec![]; let item = self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| { - let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); + let item = + this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode); unclosed_delims.append(&mut this.unclosed_delims); Ok((item?, TrailingToken::None)) })?; @@ -127,12 +130,13 @@ mut attrs: Vec, mac_allowed: bool, attrs_allowed: bool, - req_name: ReqName, + fn_parse_mode: FnParseMode, ) -> PResult<'a, Option> { 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, req_name)?; + let kind = + self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, fn_parse_mode)?; if let Some((ident, kind)) = kind { self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_token.span); @@ -192,7 +196,7 @@ lo: Span, vis: &Visibility, def: &mut Defaultness, - req_name: ReqName, + fn_parse_mode: FnParseMode, ) -> PResult<'a, Option> { let def_final = def == &Defaultness::Final; let mut def = || mem::replace(def, Defaultness::Final); @@ -219,7 +223,7 @@ (Ident::empty(), ItemKind::Use(tree)) } else if self.check_fn_front_matter(def_final) { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?; + 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 }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -407,10 +411,30 @@ fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` self.expect(&token::Not)?; // `!` - let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. - self.eat_semi_for_macro_if_needed(&args); - self.complain_if_pub_macro(vis, false); - Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) + match self.parse_mac_args() { + // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. + Ok(args) => { + self.eat_semi_for_macro_if_needed(&args); + self.complain_if_pub_macro(vis, false); + Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) + } + + Err(mut err) => { + // Maybe the user misspelled `macro_rules` (issue #91227) + if self.token.is_ident() + && path.segments.len() == 1 + && lev_distance("macro_rules", &path.segments[0].ident.to_string()) <= 3 + { + err.span_suggestion( + path.span, + "perhaps you meant to define a macro", + "macro_rules".to_string(), + Applicability::MachineApplicable, + ); + } + Err(err) + } + } } /// Recover if we parsed attributes and expected an item but there was none. @@ -733,23 +757,26 @@ &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - self.parse_assoc_item(|_| true, force_collect) + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + self.parse_assoc_item(fn_parse_mode, force_collect) } pub fn parse_trait_item( &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - self.parse_assoc_item(|edition| edition >= Edition::Edition2018, force_collect) + let fn_parse_mode = + FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false }; + self.parse_assoc_item(fn_parse_mode, force_collect) } /// Parses associated items. fn parse_assoc_item( &mut self, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - Ok(self.parse_item_(req_name, force_collect)?.map( + Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, @@ -767,6 +794,44 @@ )) } + /// Emits an error that the where clause at the end of a type alias is not + /// allowed and suggests moving it. + fn error_ty_alias_where( + &self, + before_where_clause_present: bool, + before_where_clause_span: Span, + after_predicates: &[WherePredicate], + after_where_clause_span: Span, + ) { + let mut err = + self.struct_span_err(after_where_clause_span, "where clause not allowed here"); + if !after_predicates.is_empty() { + let mut state = crate::pprust::State::new(); + if !before_where_clause_present { + state.space(); + state.word_space("where"); + } else { + state.word_space(","); + } + let mut first = true; + for p in after_predicates.iter() { + if !first { + state.word_space(","); + } + first = false; + state.print_where_predicate(p); + } + let suggestion = state.s.eof(); + err.span_suggestion( + before_where_clause_span.shrink_to_hi(), + "move it here", + suggestion, + Applicability::MachineApplicable, + ); + } + err.emit() + } + /// Parses a `type` alias with the following grammar: /// ``` /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ; @@ -779,9 +844,24 @@ // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() }; + generics.where_clause = self.parse_where_clause()?; let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; + + if self.token.is_keyword(kw::Where) { + let after_where_clause = self.parse_where_clause()?; + + self.error_ty_alias_where( + generics.where_clause.has_where_token, + generics.where_clause.span, + &after_where_clause.predicates, + after_where_clause.span, + ); + + generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter()); + } + self.expect_semi()?; Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty })))) @@ -944,7 +1024,8 @@ &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - Ok(self.parse_item_(|_| true, force_collect)?.map( + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; + Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, @@ -1483,8 +1564,16 @@ let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { let err = if self.check_fn_front_matter(false) { + let inherited_vis = Visibility { + span: rustc_span::DUMMY_SP, + kind: VisibilityKind::Inherited, + tokens: None, + }; // We use `parse_fn` to get a span for the function - if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) { + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + if let Err(mut db) = + self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis) + { db.delay_as_bug(); } let mut err = self.struct_span_err( @@ -1698,25 +1787,83 @@ /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). /// /// The function decides if, per-parameter `p`, `p` must have a pattern or just a type. +/// +/// This function pointer accepts an edition, because in edition 2015, trait declarations +/// were allowed to omit parameter names. In 2018, they became required. type ReqName = fn(Edition) -> bool; +/// Parsing configuration for functions. +/// +/// The syntax of function items is slightly different within trait definitions, +/// impl blocks, and modules. It is still parsed using the same code, just with +/// different flags set, so that even when the input is wrong and produces a parse +/// error, it still gets into the AST and the rest of the parser and +/// type checker can run. +#[derive(Clone, Copy)] +pub(crate) struct FnParseMode { + /// A function pointer that decides if, per-parameter `p`, `p` must have a + /// pattern or just a type. This field affects parsing of the parameters list. + /// + /// ```text + /// fn foo(alef: A) -> X { X::new() } + /// -----^^ affects parsing this part of the function signature + /// | + /// if req_name returns false, then this name is optional + /// + /// fn bar(A) -> X; + /// ^ + /// | + /// if req_name returns true, this is an error + /// ``` + /// + /// Calling this function pointer should only return false if: + /// + /// * The item is being parsed inside of a trait definition. + /// Within an impl block or a module, it should always evaluate + /// to true. + /// * The span is from Edition 2015. In particular, you can get a + /// 2015 span inside a 2021 crate using macros. + pub req_name: ReqName, + /// If this flag is set to `true`, then plain, semicolon-terminated function + /// prototypes are not allowed here. + /// + /// ```text + /// fn foo(alef: A) -> X { X::new() } + /// ^^^^^^^^^^^^ + /// | + /// this is always allowed + /// + /// fn bar(alef: A, bet: B) -> X; + /// ^ + /// | + /// if req_body is set to true, this is an error + /// ``` + /// + /// This field should only be set to false if the item is inside of a trait + /// definition or extern block. Within an impl block or a module, it should + /// always be set to true. + pub req_body: bool, +} + /// Parsing of functions and methods. impl<'a> Parser<'a> { /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`. fn parse_fn( &mut self, attrs: &mut Vec, - req_name: ReqName, + fn_parse_mode: FnParseMode, sig_lo: Span, + vis: &Visibility, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { - let header = self.parse_fn_front_matter()?; // `const ... fn` + let header = self.parse_fn_front_matter(vis)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` - let decl = self.parse_fn_decl(req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)` + let decl = + self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)` generics.where_clause = self.parse_where_clause()?; // `where T: Ord` let mut sig_hi = self.prev_token.span; - let body = self.parse_fn_body(attrs, &ident, &mut sig_hi)?; // `;` or `{ ... }`. + let body = self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body)?; // `;` or `{ ... }`. let fn_sig_span = sig_lo.to(sig_hi); Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body)) } @@ -1729,9 +1876,17 @@ attrs: &mut Vec, ident: &Ident, sig_hi: &mut Span, + req_body: bool, ) -> PResult<'a, Option>> { - let (inner_attrs, body) = if self.eat(&token::Semi) { + let has_semi = if req_body { + self.token.kind == TokenKind::Semi + } else { + // Only include `;` in list of expected tokens if body is not required + self.check(&TokenKind::Semi) + }; + let (inner_attrs, body) = if has_semi { // Include the trailing semicolon in the span of the signature + self.expect_semi()?; *sig_hi = self.prev_token.span; (Vec::new(), None) } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { @@ -1752,9 +1907,12 @@ .emit(); (Vec::new(), Some(self.mk_block_err(span))) } else { - if let Err(mut err) = - self.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)]) - { + let expected = if req_body { + &[token::OpenDelim(token::Brace)][..] + } else { + &[token::Semi, token::OpenDelim(token::Brace)] + }; + if let Err(mut err) = self.expected_one_of_not_found(&[], &expected) { if self.token.kind == token::CloseDelim(token::Brace) { // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in // the AST for typechecking. @@ -1806,12 +1964,15 @@ /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, /// up to and including the `fn` keyword. The formal grammar is: /// - /// ``` + /// ```text /// Extern = "extern" StringLit? ; /// FnQual = "const"? "async"? "unsafe"? Extern? ; /// FnFrontMatter = FnQual "fn" ; /// ``` - pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { + /// + /// `vis` represents the visibility that was already parsed, if any. Use + /// `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(); @@ -1837,51 +1998,94 @@ Ok(false) => unreachable!(), Err(mut err) => { // Qualifier keywords ordering check + enum WrongKw { + Duplicated(Span), + Misplaced(Span), + } - // This will allow the machine fix to directly place the keyword in the correct place - let current_qual_sp = if self.check_keyword(kw::Const) { - Some(async_start_sp) + // This will allow the machine fix to directly place the keyword in the correct place or to indicate + // that the keyword is already present and the second instance should be removed. + let wrong_kw = if self.check_keyword(kw::Const) { + match constness { + Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Const::No => Some(WrongKw::Misplaced(async_start_sp)), + } } else if self.check_keyword(kw::Async) { - Some(unsafe_start_sp) + match asyncness { + Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), + Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), + } } else if self.check_keyword(kw::Unsafe) { - Some(ext_start_sp) + match unsafety { + Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), + } } else { None }; - if let Some(current_qual_sp) = current_qual_sp { - let current_qual_sp = current_qual_sp.to(self.prev_token.span); - if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) { - let invalid_qual_sp = self.token.uninterpolated_span(); - let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap(); + // The keyword is already present, suggest removal of the second instance + if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw { + let original_kw = self + .span_to_snippet(original_sp) + .expect("Span extracted directly from keyword should always work"); + + err.span_suggestion( + self.token.uninterpolated_span(), + &format!("`{}` already used earlier, remove this one", original_kw), + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(original_sp, &format!("`{}` first seen here", original_kw)); + } + // The keyword has not been seen yet, suggest correct placement in the function front matter + else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw { + let correct_pos_sp = correct_pos_sp.to(self.prev_token.span); + if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) { + let misplaced_qual_sp = self.token.uninterpolated_span(); + let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap(); err.span_suggestion( - current_qual_sp.to(invalid_qual_sp), - &format!("`{}` must come before `{}`", invalid_qual, current_qual), - format!("{} {}", invalid_qual, current_qual), - Applicability::MachineApplicable, - ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); + correct_pos_sp.to(misplaced_qual_sp), + &format!("`{}` must come before `{}`", misplaced_qual, current_qual), + format!("{} {}", misplaced_qual, current_qual), + Applicability::MachineApplicable, + ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); } } - // Recover incorrect visibility order such as `async pub`. + // Recover incorrect visibility order such as `async pub` else if self.check_keyword(kw::Pub) { let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { - let vis = match self.parse_visibility(FollowedByType::No) { + let current_vis = match self.parse_visibility(FollowedByType::No) { Ok(v) => v, Err(mut d) => { d.cancel(); return Err(err); } }; - let vs = pprust::vis_to_string(&vis); + let vs = pprust::vis_to_string(¤t_vis); let vs = vs.trim_end(); - err.span_suggestion( - sp_start.to(self.prev_token.span), - &format!("visibility `{}` must come before `{}`", vs, snippet), - format!("{} {}", vs, snippet), - Applicability::MachineApplicable, - ); + + // There was no explicit visibility + if matches!(orig_vis.kind, VisibilityKind::Inherited) { + err.span_suggestion( + sp_start.to(self.prev_token.span), + &format!("visibility `{}` must come before `{}`", vs, snippet), + format!("{} {}", vs, snippet), + Applicability::MachineApplicable, + ); + } + // There was an explicit visibility + else { + err.span_suggestion( + current_vis.span, + "there is already a visibility modifier, remove one", + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(orig_vis.span, "explicit visibility first seen here"); + } } } return Err(err); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -14,6 +14,7 @@ pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; use diagnostics::Error; +pub(crate) use item::FnParseMode; pub use pat::{RecoverColon, RecoverComma}; pub use path::PathStyle; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/pat.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/pat.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/pat.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/pat.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,14 +3,16 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::{self as ast, AttrVec, Attribute, MacCall, Pat, PatField, PatKind, RangeEnd}; -use rustc_ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax}; +use rustc_ast::{ + self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, + PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, +}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult}; use rustc_span::source_map::{respan, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; -type Expected = Option<&'static str>; +pub(super) type Expected = Option<&'static str>; /// `Expected` for function and lambda parameter patterns. pub(super) const PARAM_EXPECTED: Expected = Some("parameter name"); @@ -98,55 +100,9 @@ // If we parsed a leading `|` which should be gated, // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. - let mut first_pat = first_pat; - if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) { - if matches!( - first_pat.kind, - PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) - | PatKind::Path(..) - ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) - { - // The pattern looks like it might be a path with a `::` -> `:` typo: - // `match foo { bar:baz => {} }` - let span = self.token.span; - // We only emit "unexpected `:`" error here if we can successfully parse the - // whole pattern correctly in that case. - let snapshot = self.clone(); - - // Create error for "unexpected `:`". - match self.expected_one_of_not_found(&[], &[]) { - Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { - Err(mut inner_err) => { - // Carry on as if we had not done anything, callers will emit a - // reasonable error. - inner_err.cancel(); - err.cancel(); - *self = snapshot; - } - Ok(pat) => { - // We've parsed the rest of the pattern. - err.span_suggestion( - span, - "maybe write a path separator here", - "::".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - first_pat = - self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild); - } - } - } - _ => { - // Carry on as if we had not done anything. This should be unreachable. - *self = snapshot; - } - }; - } - } + // Check if the user wrote `foo:bar` instead of `foo::bar`. + let first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, ra, expected); if let Some(leading_vert_span) = leading_vert_span { // If there was a leading vert, treat this as an or-pattern. This improves @@ -321,57 +277,6 @@ err.emit(); } - /// Some special error handling for the "top-level" patterns in a match arm, - /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> { - if rc == RecoverComma::No || self.token != token::Comma { - return Ok(()); - } - - // An unexpected comma after a top-level pattern is a clue that the - // user (perhaps more accustomed to some other language) forgot the - // parentheses in what should have been a tuple pattern; return a - // suggestion-enhanced error here rather than choking on the comma later. - let comma_span = self.token.span; - self.bump(); - if let Err(mut err) = self.skip_pat_list() { - // We didn't expect this to work anyway; we just wanted to advance to the - // end of the comma-sequence so we know the span to suggest parenthesizing. - err.cancel(); - } - let seq_span = lo.to(self.prev_token.span); - let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); - if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - const MSG: &str = "try adding parentheses to match on a tuple..."; - - err.span_suggestion( - seq_span, - MSG, - format!("({})", seq_snippet), - Applicability::MachineApplicable, - ); - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(",", " |"), - Applicability::MachineApplicable, - ); - } - Err(err) - } - - /// Parse and throw away a parenthesized comma separated - /// sequence of patterns until `)` is reached. - fn skip_pat_list(&mut self) -> PResult<'a, ()> { - while !self.check(&token::CloseDelim(token::Paren)) { - self.parse_pat_no_top_alt(None)?; - if !self.eat(&token::Comma) { - return Ok(()); - } - } - Ok(()) - } - /// A `|` or possibly `||` token shouldn't be here. Ban it. fn ban_illegal_vert(&mut self, lo: Option, pos: &str, ctx: &str) { let span = self.token.span; @@ -1168,7 +1073,7 @@ self.mk_pat(span, PatKind::Ident(bm, ident, None)) } - fn mk_pat(&self, span: Span, kind: PatKind) -> P { + pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P { P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/stmt.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/stmt.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/stmt.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/stmt.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,9 @@ use super::pat::RecoverComma; use super::path::PathStyle; use super::TrailingToken; -use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode}; +use super::{ + AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, +}; use crate::maybe_whole; use rustc_ast as ast; @@ -79,9 +81,13 @@ } else { self.parse_stmt_path_start(lo, attrs) }? - } else if let Some(item) = - self.parse_item_common(attrs.clone(), false, true, |_| true, force_collect)? - { + } else if let Some(item) = self.parse_item_common( + attrs.clone(), + false, + true, + FnParseMode { req_name: |_| true, req_body: true }, + force_collect, + )? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/ty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/ty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/ty.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_parse/src/parser/ty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -474,7 +474,13 @@ params: Vec, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, TyKind> { - let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?; + let inherited_vis = rustc_ast::Visibility { + span: rustc_span::DUMMY_SP, + kind: rustc_ast::VisibilityKind::Inherited, + tokens: None, + }; + let ast::FnHeader { ext, unsafety, constness, asyncness } = + self.parse_fn_front_matter(&inherited_vis)?; let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_attr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_attr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_attr.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_attr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -32,7 +32,7 @@ match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, hir::ImplItemKind::Fn(..) => { - let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()); + let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()).expect_owner(); let containing_item = tcx.hir().expect_item(parent_hir_id); let containing_impl_is_for_trait = match &containing_item.kind { hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), @@ -58,7 +58,7 @@ tcx: TyCtxt<'tcx>, } -impl CheckAttrVisitor<'tcx> { +impl CheckAttrVisitor<'_> { /// Checks any attribute. fn check_attributes( &self, @@ -382,7 +382,7 @@ &self, hir_id: HirId, attr_span: &Span, - attrs: &'hir [Attribute], + attrs: &[Attribute], span: &Span, target: Target, ) -> bool { @@ -582,7 +582,7 @@ Target::Impl => Some("implementation block"), Target::ForeignMod => Some("extern block"), Target::AssocTy => { - let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner(); let containing_item = self.tcx.hir().expect_item(parent_hir_id); if Target::from_item(containing_item) == Target::Impl { Some("type alias in implementation block") @@ -591,7 +591,7 @@ } } Target::AssocConst => { - let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner(); let containing_item = self.tcx.hir().expect_item(parent_hir_id); // We can't link to trait impl's consts. let err = "associated constant in trait implementation block"; @@ -607,7 +607,7 @@ return err_fn(meta.span(), &format!("isn't allowed on {}", err)); } let item_name = self.tcx.hir().name(hir_id); - if &*item_name.as_str() == doc_alias { + if item_name.as_str() == doc_alias { return err_fn(meta.span(), "is the same as the item's name"); } let span = meta.span(); @@ -636,7 +636,7 @@ LitKind::Str(s, _) => { if !self.check_doc_alias_value( v, - &s.as_str(), + s.as_str(), hir_id, target, true, @@ -1481,7 +1481,7 @@ /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, - attrs: &'hir [Attribute], + attrs: &[Attribute], span: &Span, target: Target, item: Option>, @@ -1663,7 +1663,7 @@ } } - fn check_used(&self, attrs: &'hir [Attribute], target: Target) { + fn check_used(&self, attrs: &[Attribute], target: Target) { for attr in attrs { if attr.has_name(sym::used) && target != Target::Static { self.tcx @@ -1842,7 +1842,7 @@ } } -impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1953,7 +1953,12 @@ } } +// FIXME: Fix "Cannot determine resolution" error and remove built-in macros +// from this check. fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { + // Check for builtin attributes at the crate level + // which were unsuccessfully resolved due to cannot determine + // resolution for the attribute macro error. const ATTRS_TO_CHECK: &[Symbol] = &[ sym::macro_export, sym::repr, @@ -1961,20 +1966,39 @@ sym::automatically_derived, sym::start, sym::rustc_main, + sym::derive, + sym::test, + sym::test_case, + sym::global_allocator, + sym::bench, ]; for attr in attrs { - for attr_to_check in ATTRS_TO_CHECK { - if attr.has_name(*attr_to_check) { - tcx.sess - .struct_span_err( + // This function should only be called with crate attributes + // which are inner attributes always but lets check to make sure + if attr.style == AttrStyle::Inner { + for attr_to_check in ATTRS_TO_CHECK { + if attr.has_name(*attr_to_check) { + let mut err = tcx.sess.struct_span_err( attr.span, &format!( "`{}` attribute cannot be used at crate level", attr_to_check.to_ident_string() ), - ) - .emit(); + ); + // Only emit an error with a suggestion if we can create a + // string out of the attribute span + if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) { + let replacement = src.replace("#!", "#"); + err.span_suggestion_verbose( + attr.span, + "perhaps you meant to use an outer attribute", + replacement, + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit() + } } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_const.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_const.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_const.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/check_const.rs 2022-02-23 04:07:21.000000000 +0000 @@ -78,7 +78,7 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> { /// check for const trait impls, and errors if the impl uses provided/default functions /// of the trait being implemented; as those provided functions can be non-const. - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { + fn visit_item<'hir>(&mut self, item: &'hir hir::Item<'hir>) { let _: Option<_> = try { if let hir::ItemKind::Impl(ref imp) = item.kind { if let hir::Constness::Const = imp.constness { @@ -134,11 +134,11 @@ }; } - fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {} + fn visit_trait_item<'hir>(&mut self, _: &'hir hir::TraitItem<'hir>) {} - fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {} + fn visit_impl_item<'hir>(&mut self, _: &'hir hir::ImplItem<'hir>) {} - fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {} + fn visit_foreign_item<'hir>(&mut self, _: &'hir hir::ForeignItem<'hir>) {} } #[derive(Copy, Clone)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/dead.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/dead.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/dead.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/dead.rs 2022-02-23 04:07:21.000000000 +0000 @@ -150,7 +150,7 @@ #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { - fn check_for_self_assign_helper( + fn check_for_self_assign_helper<'tcx>( tcx: TyCtxt<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, lhs: &'tcx hir::Expr<'tcx>, @@ -600,7 +600,7 @@ live_symbols: FxHashSet, } -impl DeadVisitor<'tcx> { +impl<'tcx> DeadVisitor<'tcx> { fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool { let should_warn = matches!( item.kind, @@ -672,7 +672,7 @@ } } -impl Visitor<'tcx> for DeadVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> { type Map = Map<'tcx>; /// Walk nested items in place so that we don't report dead-code diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/intrinsicck.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/intrinsicck.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/intrinsicck.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/intrinsicck.rs 2022-02-23 04:07:21.000000000 +0000 @@ -62,7 +62,7 @@ ty } -impl ExprVisitor<'tcx> { +impl<'tcx> ExprVisitor<'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { self.tcx.fn_sig(def_id).abi() == RustIntrinsic && self.tcx.item_name(def_id) == sym::transmute @@ -487,7 +487,7 @@ } } -impl Visitor<'tcx> for ItemVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -504,7 +504,7 @@ } } -impl Visitor<'tcx> for ExprVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lang_items.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lang_items.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lang_items.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lang_items.rs 2022-02-23 04:07:21.000000000 +0000 @@ -28,7 +28,7 @@ tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { +impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { self.check_for_lang(Target::from_item(item), item.hir_id()); @@ -50,7 +50,7 @@ fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {} } -impl LanguageItemCollector<'tcx> { +impl<'tcx> LanguageItemCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> { LanguageItemCollector { tcx, items: LanguageItems::new() } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/layout_test.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/layout_test.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/layout_test.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/layout_test.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,7 +20,7 @@ tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match item.kind { ItemKind::TyAlias(..) @@ -42,7 +42,7 @@ fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {} } -impl LayoutTest<'tcx> { +impl<'tcx> LayoutTest<'tcx> { fn dump_layout_of(&self, item_def_id: LocalDefId, item: &hir::Item<'tcx>, attr: &Attribute) { let tcx = self.tcx; let param_env = self.tcx.param_env(item_def_id); @@ -114,7 +114,7 @@ param_env: ParamEnv<'tcx>, } -impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { @@ -127,19 +127,19 @@ } } -impl HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } } -impl HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { fn param_env(&self) -> ParamEnv<'tcx> { self.param_env } } -impl HasDataLayout for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasDataLayout for UnwrapLayoutCx<'tcx> { fn data_layout(&self) -> &TargetDataLayout { self.tcx.data_layout() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib_features.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib_features.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib_features.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib_features.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,7 @@ // and `#[unstable (..)]`), but are not declared in one single location // (unlike lang features), which means we need to collect them instead. -use rustc_ast::{Attribute, MetaItem, MetaItemKind}; +use rustc_ast::{Attribute, MetaItemKind}; use rustc_errors::struct_span_err; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; @@ -23,7 +23,7 @@ lib_features: LibFeatures, } -impl LibFeatureCollector<'tcx> { +impl<'tcx> LibFeatureCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> { LibFeatureCollector { tcx, lib_features: new_lib_features() } } @@ -34,8 +34,8 @@ // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) { - let meta_item = attr.meta(); - if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta_item { + let meta_kind = attr.meta_kind(); + if let Some(MetaItemKind::List(ref metas)) = meta_kind { let mut feature = None; let mut since = None; for meta in metas { @@ -110,7 +110,7 @@ } } -impl Visitor<'tcx> for LibFeatureCollector<'tcx> { +impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -124,12 +124,12 @@ } } -fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { +fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); tcx.hir().walk_attributes(&mut collector); collector.lib_features } pub fn provide(providers: &mut Providers) { - providers.get_lib_features = get_lib_features; + providers.lib_features = lib_features; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,9 +6,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(nll)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/liveness.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/liveness.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/liveness.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/liveness.rs 2022-02-23 04:07:21.000000000 +0000 @@ -198,7 +198,7 @@ lnks: IndexVec, } -impl IrMaps<'tcx> { +impl<'tcx> IrMaps<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> IrMaps<'tcx> { IrMaps { tcx, @@ -429,8 +429,8 @@ intravisit::walk_expr(self, expr); } - hir::ExprKind::Let(ref pat, ..) => { - self.add_from_pat(pat); + hir::ExprKind::Let(let_expr) => { + self.add_from_pat(let_expr.pat); intravisit::walk_expr(self, expr); } @@ -856,9 +856,9 @@ }) } - hir::ExprKind::Let(ref pat, ref scrutinee, _) => { - let succ = self.propagate_through_expr(scrutinee, succ); - self.define_bindings_in_pat(pat, succ) + hir::ExprKind::Let(let_expr) => { + let succ = self.propagate_through_expr(let_expr.init, succ); + self.define_bindings_in_pat(let_expr.pat, succ) } // Note that labels have been resolved, so we don't need to look @@ -1401,8 +1401,8 @@ } } - hir::ExprKind::Let(ref pat, ..) => { - this.check_unused_vars_in_pat(pat, None, |_, _, _, _| {}); + hir::ExprKind::Let(let_expr) => { + this.check_unused_vars_in_pat(let_expr.pat, None, |_, _, _, _| {}); } // no correctness conditions related to liveness @@ -1464,7 +1464,7 @@ if name == kw::Empty { return None; } - let name: &str = &name.as_str(); + let name = name.as_str(); if name.as_bytes()[0] == b'_' { return None; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/naked_functions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/naked_functions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/naked_functions.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/naked_functions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -37,7 +37,7 @@ fn visit_fn( &mut self, - fk: FnKind<'v>, + fk: FnKind<'_>, _fd: &'tcx hir::FnDecl<'tcx>, body_id: hir::BodyId, span: Span, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/reachable.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/reachable.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/reachable.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/reachable.rs 2022-02-23 04:07:21.000000000 +0000 @@ -22,7 +22,7 @@ // Returns true if the given item must be inlined because it may be // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. -fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { +fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { if attrs.requests_inline() { return true; } @@ -173,8 +173,7 @@ // Check the impl. If the generics on the self // type of the impl require inlining, this method // does too. - let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did); - match self.tcx.hir().expect_item(impl_hir_id).kind { + match self.tcx.hir().expect_item(impl_did).kind { hir::ItemKind::Impl { .. } => { let generics = self.tcx.generics_of(impl_did); generics.requires_monomorphization(self.tcx) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/region.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/region.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/region.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/region.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt}; +use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt}; use rustc_index::vec::Idx; use rustc_middle::middle::region::*; use rustc_middle::ty::query::Providers; @@ -421,11 +421,14 @@ // Mark this expr's scope and all parent scopes as containing `yield`. let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; loop { - let data = YieldData { - span: expr.span, - expr_and_pat_count: visitor.expr_and_pat_count, - source: *source, + let span = match expr.kind { + hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { + expr.span.shrink_to_hi().to(expr.span) + } + _ => expr.span, }; + let data = + YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source }; visitor.scope_tree.yield_in_scope.insert(scope, data); if visitor.pessimistic_yield { debug!("resolve_expr in pessimistic_yield - marking scope {:?} for fixup", scope); @@ -837,19 +840,7 @@ let body = tcx.hir().body(body_id); visitor.scope_tree.root_body = Some(body.value.hir_id); - - // If the item is an associated const or a method, - // record its impl/trait parent, as it can also have - // lifetime parameters free in this body. - match tcx.hir().get(id) { - Node::ImplItem(_) | Node::TraitItem(_) => { - visitor.scope_tree.root_parent = Some(tcx.hir().get_parent_item(id)); - } - _ => {} - } - visitor.visit_body(body); - visitor.scope_tree } else { ScopeTree::default() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/stability.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/stability.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/stability.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/stability.rs 2022-02-23 04:07:21.000000000 +0000 @@ -655,7 +655,7 @@ // stable (assuming they have not inherited instability from their parent). } -fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { +fn stability_index<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { let is_staged_api = tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api; let mut staged_api = FxHashMap::default(); @@ -737,7 +737,7 @@ tcx: TyCtxt<'tcx>, } -impl Visitor<'tcx> for Checker<'tcx> { +impl<'tcx> Visitor<'tcx> for Checker<'tcx> { type Map = Map<'tcx>; /// Because stability levels are scoped lexically, we want to walk @@ -866,7 +866,7 @@ fully_stable: bool, } -impl Visitor<'tcx> for CheckTraitImplStable<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -970,7 +970,7 @@ // We always collect the lib features declared in the current crate, even if there are // no unknown features, because the collection also does feature attribute validation. - let local_defined_features = tcx.lib_features().to_vec(); + let local_defined_features = tcx.lib_features(()).to_vec(); if !remaining_lib_features.is_empty() { check_features(&mut remaining_lib_features, &local_defined_features); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/upvars.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/upvars.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/upvars.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/upvars.rs 2022-02-23 04:07:21.000000000 +0000 @@ -42,7 +42,7 @@ locals: FxHashSet, } -impl Visitor<'tcx> for LocalCollector { +impl<'tcx> Visitor<'tcx> for LocalCollector { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -71,7 +71,7 @@ } } -impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/weak_lang_items.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/weak_lang_items.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/weak_lang_items.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_passes/src/weak_lang_items.rs 2022-02-23 04:07:21.000000000 +0000 @@ -67,10 +67,16 @@ } else if item == LangItem::Oom { if !tcx.features().default_alloc_error_handler { tcx.sess.err("`#[alloc_error_handler]` function required, but not found"); - tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler"); + tcx.sess.note_without_error("use `#![feature(default_alloc_error_handler)]` for a default error handler"); } } else { - tcx.sess.err(&format!("language item required, but not found: `{}`", name)); + tcx + .sess + .diagnostic() + .struct_err(&format!("language item required, but not found: `{}`", name)) + .note(&format!("this can occur when a binary crate with `#![no_std]` is compiled for a target where `{}` is defined in the standard library", name)) + .help(&format!("you may be able to compile for a target that doesn't need `{}`, specify a target with `--target` or in `.cargo/config`", name)) + .emit(); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/Cargo.toml 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -8,6 +8,7 @@ doctest = false [dependencies] +libloading = "0.7.1" rustc_middle = { path = "../rustc_middle" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/src/load.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/src/load.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/src/load.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_plugin_impl/src/load.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,6 +1,7 @@ //! Used by `rustc` when loading a plugin. use crate::Registry; +use libloading::Library; use rustc_ast::Crate; use rustc_errors::struct_span_err; use rustc_metadata::locator; @@ -56,37 +57,28 @@ ident: Ident, ) { let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); - let fun = dylink_registrar(sess, ident.span, lib); + let fun = dylink_registrar(lib).unwrap_or_else(|err| { + // This is fatal: there are almost certainly macros we need inside this crate, so + // continuing would spew "macro undefined" errors. + sess.span_fatal(ident.span, &err.to_string()); + }); plugins.push(fun); } -// Dynamically link a registrar function into the compiler process. -fn dylink_registrar(sess: &Session, span: Span, path: PathBuf) -> PluginRegistrarFn { - use rustc_metadata::dynamic_lib::DynamicLibrary; - +/// Dynamically link a registrar function into the compiler process. +fn dylink_registrar(lib_path: PathBuf) -> Result { // Make sure the path contains a / or the linker will search for it. - let path = env::current_dir().unwrap().join(&path); + let lib_path = env::current_dir().unwrap().join(&lib_path); - let lib = match DynamicLibrary::open(&path) { - Ok(lib) => lib, - // this is fatal: there are almost certainly macros we need - // inside this crate, so continue would spew "macro undefined" - // errors - Err(err) => sess.span_fatal(span, &err), - }; - - unsafe { - let registrar = match lib.symbol("__rustc_plugin_registrar") { - Ok(registrar) => mem::transmute::<*mut u8, PluginRegistrarFn>(registrar), - // again fatal if we can't register macros - Err(err) => sess.span_fatal(span, &err), - }; - - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can make things that will live arbitrarily long - // (e.g., an Rc cycle or a thread). - mem::forget(lib); + let lib = unsafe { Library::new(&lib_path) }?; - registrar - } + let registrar_sym = unsafe { lib.get::(b"__rustc_plugin_registrar") }?; + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long + // (e.g., an Rc cycle or a thread). + let registrar_sym = unsafe { registrar_sym.into_raw() }; + mem::forget(lib); + + Ok(*registrar_sym) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_privacy/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_privacy/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_privacy/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_privacy/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,4 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(in_band_lifetimes)] #![feature(nll)] #![feature(control_flow_enum)] #![feature(try_blocks)] @@ -310,7 +309,7 @@ has_pub_restricted: bool, } -impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for PubRestrictedVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -432,7 +431,7 @@ ev: &'a mut EmbargoVisitor<'tcx>, } -impl EmbargoVisitor<'tcx> { +impl<'tcx> EmbargoVisitor<'tcx> { fn get(&self, def_id: LocalDefId) -> Option { self.access_levels.map.get(&def_id).copied() } @@ -559,8 +558,7 @@ // have normal hygine, so we can treat them like other items without type // privacy and mark them reachable. DefKind::Macro(_) => { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let item = self.tcx.hir().expect_item(hir_id); + let item = self.tcx.hir().expect_item(def_id); if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind { if vis.is_accessible_from(module.to_def_id(), self.tcx) { self.update(def_id, level); @@ -581,8 +579,7 @@ DefKind::Struct | DefKind::Union => { // While structs and unions have type privacy, their fields do not. if vis.is_public() { - let item = - self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id)); + let item = self.tcx.hir().expect_item(def_id); if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { @@ -653,9 +650,7 @@ // If the module is `self`, i.e. the current crate, // there will be no corresponding item. .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE) - .and_then(|def_id| { - def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id)) - }) + .and_then(|def_id| def_id.as_local()) .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) { if let hir::ItemKind::Mod(m) = &item.kind { @@ -678,7 +673,7 @@ } } -impl Visitor<'tcx> for EmbargoVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -948,7 +943,7 @@ } } -impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { +impl ReachEverythingInTheInterfaceVisitor<'_, '_> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { @@ -987,7 +982,7 @@ } } -impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx } @@ -1417,7 +1412,7 @@ } } -impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1804,7 +1799,7 @@ in_assoc_ty: bool, } -impl SearchInterfaceForPrivateItemsVisitor<'tcx> { +impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { for param in &self.tcx.generics_of(self.item_def_id).params { match param.kind { @@ -1925,7 +1920,7 @@ } } -impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -2069,7 +2064,11 @@ // Subitems of trait impls have inherited publicity. hir::ItemKind::Impl(ref impl_) => { let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); - self.check(item.def_id, impl_vis).generics().predicates(); + // check that private components do not appear in the generics or predicates of inherent impls + // this check is intentionally NOT performed for impls of traits, per #90586 + if impl_.of_trait.is_none() { + self.check(item.def_id, impl_vis).generics().predicates(); + } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/keys.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/keys.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/keys.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/keys.rs 2022-02-23 04:07:21.000000000 +0000 @@ -151,7 +151,7 @@ } } -impl Key for (ty::Instance<'tcx>, LocalDefId) { +impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) { #[inline(always)] fn query_crate_is_local(&self) -> bool { true diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(nll)] #![feature(min_specialization)] #![feature(once_cell)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/on_disk_cache.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/on_disk_cache.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/on_disk_cache.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/on_disk_cache.rs 2022-02-23 04:07:21.000000000 +0000 @@ -158,7 +158,7 @@ // Wrap in a scope so we can borrow `data`. let footer: Footer = { - let mut decoder = opaque::Decoder::new(&data[..], start_pos); + let mut decoder = opaque::Decoder::new(&data, start_pos); // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. @@ -212,7 +212,7 @@ /// Cache promotions require invoking queries, which needs to read the serialized data. /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be /// deleted, hence we won't be able to refer to its memmapped data. - fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) { + fn drop_serialized_data(&self, tcx: TyCtxt<'_>) { // Load everything into memory so we can write it out to the on-disk // cache. The vast majority of cacheable query results should already // be in memory, so this should be a cheap operation. @@ -495,6 +495,20 @@ .entry(index) .or_insert_with(|| { let stable_id = file_index_to_stable_id[&index].translate(tcx); + + // If this `SourceFile` is from a foreign crate, then make sure + // that we've imported all of the source files from that crate. + // This has usually already been done during macro invocation. + // However, when encoding query results like `TypeckResults`, + // we might encode an `AdtDef` for a foreign type (because it + // was referenced in the body of the function). There is no guarantee + // that we will load the source files from that crate during macro + // expansion, so we use `import_source_files` to ensure that the foreign + // source files are actually imported before we call `source_file_by_stable_id`. + if stable_id.cnum != LOCAL_CRATE { + self.tcx.cstore_untracked().import_source_files(self.tcx.sess, stable_id.cnum); + } + source_map .source_file_by_stable_id(stable_id) .expect("failed to lookup `SourceFile` in new context") diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/plumbing.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/plumbing.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/plumbing.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/plumbing.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ } } -impl HasDepContext for QueryCtxt<'tcx> { +impl<'tcx> HasDepContext for QueryCtxt<'tcx> { type DepKind = rustc_middle::dep_graph::DepKind; type DepContext = TyCtxt<'tcx>; @@ -41,7 +41,7 @@ } } -impl QueryContext for QueryCtxt<'tcx> { +impl QueryContext for QueryCtxt<'_> { fn current_query_job(&self) -> Option> { tls::with_related_context(**self, |icx| icx.query) } @@ -130,7 +130,7 @@ pub(super) fn encode_query_results( self, - encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, + encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx, opaque::FileEncoder>, query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, ) -> opaque::FileEncodeResult { macro_rules! encode_queries { @@ -231,6 +231,16 @@ }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* @@ -247,6 +257,7 @@ // Create an eponymous constructor for each query. $(#[allow(nonstandard_style)] $(#[$attr])* pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame { + opt_remap_env_constness!([$($modifiers)*][key]); let kind = dep_graph::DepKind::$name; let name = stringify!($name); // Disable visible paths printing for performance reasons. @@ -500,7 +511,7 @@ } } - impl QueryEngine<'tcx> for Queries<'tcx> { + impl<'tcx> QueryEngine<'tcx> for Queries<'tcx> { fn as_any(&'tcx self) -> &'tcx dyn std::any::Any { let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) }; this as _ @@ -521,6 +532,7 @@ lookup: QueryLookup, mode: QueryMode, ) -> Option> { + opt_remap_env_constness!([$($modifiers)*][key]); let qcx = QueryCtxt { tcx, queries: self }; get_query::, _>(qcx, span, key, lookup, mode) })* diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/profiling_support.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/profiling_support.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/profiling_support.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_impl/src/profiling_support.rs 2022-02-23 04:07:21.000000000 +0000 @@ -61,8 +61,8 @@ match def_key.disambiguated_data.data { DefPathData::CrateRoot => { - crate_name = self.tcx.crate_name(def_id.krate).as_str(); - name = &*crate_name; + crate_name = self.tcx.crate_name(def_id.krate); + name = crate_name.as_str(); dis = ""; end_index = 3; } @@ -295,7 +295,7 @@ /// If we are recording only summary data, the ids will point to /// just the query names. If we are recording query keys too, we /// allocate the corresponding strings here. -pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'tcx>) { +pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { if !tcx.prof.enabled() { return; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/dep_graph/graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/dep_graph/graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/dep_graph/graph.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/dep_graph/graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -88,6 +88,11 @@ previous_work_products: FxHashMap, dep_node_debug: Lock, String>>, + + /// Used by incremental compilation tests to assert that + /// a particular query result was decoded from disk + /// (not just marked green) + debug_loaded_from_disk: Lock>>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Fingerprint @@ -135,6 +140,7 @@ processed_side_effects: Default::default(), previous: prev_graph, colors: DepNodeColorMap::new(prev_graph_node_count), + debug_loaded_from_disk: Default::default(), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), } @@ -438,6 +444,14 @@ &self.data.as_ref().unwrap().previous_work_products } + pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { + self.data.as_ref().unwrap().debug_loaded_from_disk.lock().insert(dep_node); + } + + pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { + self.data.as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node) + } + #[inline(always)] pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) where diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/ich/impls_hir.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/ich/impls_hir.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/ich/impls_hir.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/ich/impls_hir.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,8 +3,7 @@ use crate::ich::hcx::BodyResolver; use crate::ich::{NodeIdHashingMode, StableHashingContext}; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use std::mem; @@ -47,28 +46,6 @@ }) } - #[inline] - fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { - let hcx = self; - let hir::Mod { inner: ref inner_span, ref item_ids } = *module; - - inner_span.hash_stable(hcx, hasher); - - // Combining the `DefPathHash`s directly is faster than feeding them - // into the hasher. Because we use a commutative combine, we also don't - // have to sort the array. - let item_ids_hash = item_ids - .iter() - .map(|id| { - let def_path_hash = id.to_stable_hash_key(hcx); - def_path_hash.0 - }) - .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b)); - - item_ids.len().hash_stable(hcx, hasher); - item_ids_hash.hash_stable(hcx, hasher); - } - fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { self.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { hir_id: _, ref span, ref kind } = *expr; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,10 +2,8 @@ #![feature(bool_to_option)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #![feature(extern_types)] #[macro_use] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/query/plumbing.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/query/plumbing.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/query/plumbing.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_query_system/src/query/plumbing.rs 2022-02-23 04:07:21.000000000 +0000 @@ -519,6 +519,10 @@ prof_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some(result) = result { + if unlikely!(tcx.dep_context().sess().opts.debugging_opts.query_dep_graph) { + dep_graph.mark_debug_loaded_from_disk(*dep_node) + } + let prev_fingerprint = tcx .dep_context() .dep_graph() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/build_reduced_graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/build_reduced_graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/build_reduced_graph.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/build_reduced_graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -108,7 +108,7 @@ /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, /// but they cannot use def-site hygiene, so the assumption holds /// (). - fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { + crate fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { loop { match self.get_module(def_id) { Some(module) => return module, @@ -651,11 +651,6 @@ /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &'b Item) { - if matches!(item.kind, ItemKind::Mod(..)) && item.ident.name == kw::Empty { - // Fake crate root item from expand. - return; - } - let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; @@ -683,75 +678,13 @@ } ItemKind::ExternCrate(orig_name) => { - let module = if orig_name.is_none() && ident.name == kw::SelfLower { - self.r - .session - .struct_span_err(item.span, "`extern crate self;` requires renaming") - .span_suggestion( - item.span, - "try", - "extern crate self as name;".into(), - Applicability::HasPlaceholders, - ) - .emit(); - return; - } else if orig_name == Some(kw::SelfLower) { - self.r.graph_root - } else { - let crate_id = self.r.crate_loader.process_extern_crate( - item, - &self.r.definitions, - local_def_id, - ); - self.r.extern_crate_map.insert(local_def_id, crate_id); - self.r.expect_module(crate_id.as_def_id()) - }; - - let used = self.process_macro_use_imports(item, module); - let binding = - (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); - let import = self.r.arenas.alloc_import(Import { - kind: ImportKind::ExternCrate { source: orig_name, target: ident }, - root_id: item.id, - id: item.id, - parent_scope: self.parent_scope, - imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - has_attributes: !item.attrs.is_empty(), - use_span_with_attributes: item.span_with_attributes(), - use_span: item.span, - root_span: item.span, - span: item.span, - module_path: Vec::new(), - vis: Cell::new(vis), - used: Cell::new(used), - }); - self.r.potentially_unused_imports.push(import); - let imported_binding = self.r.import(binding, import); - if ptr::eq(parent, self.r.graph_root) { - if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) - { - if expansion != LocalExpnId::ROOT - && orig_name.is_some() - && entry.extern_crate_item.is_none() - { - let msg = "macro-expanded `extern crate` items cannot \ - shadow names passed with `--extern`"; - self.r.session.span_err(item.span, msg); - } - } - let entry = - self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( - ExternPreludeEntry { - extern_crate_item: None, - introduced_by_item: true, - }, - ); - entry.extern_crate_item = Some(imported_binding); - if orig_name.is_some() { - entry.introduced_by_item = true; - } - } - self.r.define(parent, ident, TypeNS, imported_binding); + self.build_reduced_graph_for_extern_crate( + orig_name, + item, + local_def_id, + vis, + parent, + ); } ItemKind::Mod(..) => { @@ -889,6 +822,87 @@ } } + fn build_reduced_graph_for_extern_crate( + &mut self, + orig_name: Option, + item: &Item, + local_def_id: LocalDefId, + vis: ty::Visibility, + parent: Module<'a>, + ) { + let ident = item.ident; + let sp = item.span; + let parent_scope = self.parent_scope; + let expansion = parent_scope.expansion; + + let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower { + self.r + .session + .struct_span_err(item.span, "`extern crate self;` requires renaming") + .span_suggestion( + item.span, + "rename the `self` crate to be able to import it", + "extern crate self as name;".into(), + Applicability::HasPlaceholders, + ) + .emit(); + return; + } else if orig_name == Some(kw::SelfLower) { + Some(self.r.graph_root) + } else { + self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map( + |crate_id| { + self.r.extern_crate_map.insert(local_def_id, crate_id); + self.r.expect_module(crate_id.as_def_id()) + }, + ) + } + .map(|module| { + let used = self.process_macro_use_imports(item, module); + let binding = + (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); + (used, Some(ModuleOrUniformRoot::Module(module)), binding) + }) + .unwrap_or((true, None, self.r.dummy_binding)); + let import = self.r.arenas.alloc_import(Import { + kind: ImportKind::ExternCrate { source: orig_name, target: ident }, + root_id: item.id, + id: item.id, + parent_scope: self.parent_scope, + imported_module: Cell::new(module), + has_attributes: !item.attrs.is_empty(), + use_span_with_attributes: item.span_with_attributes(), + use_span: item.span, + root_span: item.span, + span: item.span, + module_path: Vec::new(), + vis: Cell::new(vis), + used: Cell::new(used), + }); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); + if ptr::eq(parent, self.r.graph_root) { + if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { + if expansion != LocalExpnId::ROOT + && orig_name.is_some() + && entry.extern_crate_item.is_none() + { + let msg = "macro-expanded `extern crate` items cannot \ + shadow names passed with `--extern`"; + self.r.session.span_err(item.span, msg); + } + } + let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( + ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true }, + ); + entry.extern_crate_item = Some(imported_binding); + if orig_name.is_some() { + entry.introduced_by_item = true; + } + } + self.r.define(parent, ident, TypeNS, imported_binding); + } + /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { let local_def_id = self.r.local_def_id(item.id); @@ -1002,10 +1016,7 @@ self.insert_field_names(def_id, field_names); } Res::Def(DefKind::AssocFn, def_id) => { - if cstore - .associated_item_cloned_untracked(def_id, self.r.session) - .fn_has_self_parameter - { + if cstore.fn_has_self_parameter_untracked(def_id) { self.r.has_self.insert(def_id); } } @@ -1499,4 +1510,13 @@ visit::walk_variant(self, variant); } + + fn visit_crate(&mut self, krate: &'b ast::Crate) { + if krate.is_placeholder { + self.visit_invoc_in_module(krate.id); + } else { + visit::walk_crate(self, krate); + self.contains_macro_use(&krate.attrs); + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/check_unused.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/check_unused.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/check_unused.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/check_unused.rs 2022-02-23 04:07:21.000000000 +0000 @@ -24,6 +24,7 @@ // in the last step use crate::imports::ImportKind; +use crate::module_to_string; use crate::Resolver; use rustc_ast as ast; @@ -314,12 +315,29 @@ "remove the unused import" }; + let parent_module = visitor.r.get_nearest_non_block_module( + visitor.r.local_def_id(unused.use_tree_id).to_def_id(), + ); + let test_module_span = match module_to_string(parent_module) { + Some(module) + if module == "test" + || module == "tests" + || module.starts_with("test_") + || module.starts_with("tests_") + || module.ends_with("_test") + || module.ends_with("_tests") => + { + Some(parent_module.span) + } + _ => None, + }; + visitor.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, unused.use_tree_id, ms, &msg, - BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes), + BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span), ); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/def_collector.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/def_collector.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/def_collector.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/def_collector.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions::*; use rustc_span::hygiene::LocalExpnId; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::sym; use rustc_span::Span; use tracing::debug; @@ -92,10 +92,7 @@ // information we encapsulate into, the better let def_data = match &i.kind { ItemKind::Impl { .. } => DefPathData::Impl, - ItemKind::Mod(..) if i.ident.name == kw::Empty => { - // Fake crate root item from expand. - return visit::walk_item(self, i); - } + ItemKind::ForeignMod(..) => DefPathData::ForeignMod, ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) @@ -103,7 +100,6 @@ | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::ExternCrate(..) - | ItemKind::ForeignMod(..) | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { DefPathData::ValueNs(i.ident.name) @@ -346,4 +342,12 @@ fn visit_field_def(&mut self, field: &'a FieldDef) { self.collect_field(field, None); } + + fn visit_crate(&mut self, krate: &'a Crate) { + if krate.is_placeholder { + self.visit_macro_invoc(krate.id) + } else { + visit::walk_crate(self, krate) + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/diagnostics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/diagnostics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/diagnostics.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/diagnostics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,3 @@ -use std::cmp::Reverse; use std::ptr; use rustc_ast::{self as ast, Path}; @@ -784,7 +783,7 @@ }); // Make sure error reporting is deterministic. - suggestions.sort_by_cached_key(|suggestion| suggestion.candidate.as_str()); + suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); match find_best_match_for_name( &suggestions.iter().map(|suggestion| suggestion.candidate).collect::>(), @@ -896,8 +895,11 @@ // a note about editions let note = if let Some(did) = did { let requires_note = !did.is_local() - && this.cstore().item_attrs(did, this.session).iter().any( - |attr| { + && this + .cstore() + .item_attrs_untracked(did, this.session) + .iter() + .any(|attr| { if attr.has_name(sym::rustc_diagnostic_item) { [sym::TryInto, sym::TryFrom, sym::FromIterator] .map(|x| Some(x)) @@ -905,8 +907,7 @@ } else { false } - }, - ); + }); requires_note.then(|| { format!( @@ -1178,7 +1179,7 @@ fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { let res = b.res(); - if b.span.is_dummy() { + if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() { // These already contain the "built-in" prefix or look bad with it. let add_built_in = !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod); @@ -1186,7 +1187,7 @@ ("", " from prelude") } else if b.is_extern_crate() && !b.is_import() - && self.session.opts.externs.get(&ident.as_str()).is_some() + && self.session.opts.externs.get(ident.as_str()).is_some() { ("", " passed with `--extern`") } else if add_built_in { @@ -1481,12 +1482,12 @@ return None; } - // Sort extern crate names in reverse order to get + // Sort extern crate names in *reverse* order to get // 1) some consistent ordering for emitted diagnostics, and // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::>(); - extern_crate_names.sort_by_key(|name| Reverse(name.as_str())); + extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/diagnostics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/diagnostics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/diagnostics.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/diagnostics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -231,7 +231,7 @@ let is_assoc_fn = self.self_type_is_available(span); // 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()) && is_assoc_fn { err.span_suggestion_short( span, "you might have meant to use `self` here instead", @@ -298,11 +298,16 @@ .get(0) .map(|p| (p.span.shrink_to_lo(), "&self, ")) .unwrap_or_else(|| { + // Try to look for the "(" after the function name, if possible. + // This avoids placing the suggestion into the visibility specifier. + let span = fn_kind + .ident() + .map_or(*span, |ident| span.with_lo(ident.span.hi())); ( self.r .session .source_map() - .span_through_char(*span, '(') + .span_through_char(span, '(') .shrink_to_hi(), "&self", ) @@ -1353,7 +1358,7 @@ let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. - names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str()); + names.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); match find_best_match_for_name( &names.iter().map(|suggestion| suggestion.candidate).collect::>(), @@ -1372,7 +1377,7 @@ fn likely_rust_type(path: &[Segment]) -> Option { let name = path[path.len() - 1].ident.as_str(); // Common Java types - Some(match &*name { + Some(match name { "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes. "short" => sym::i16, "boolean" => sym::bool, @@ -1735,7 +1740,7 @@ (generics.span, format!("<{}>", ident)) }; // Do not suggest if this is coming from macro expansion. - if !span.from_expansion() { + if span.can_be_used_for_suggestions() { return Some(( span.shrink_to_hi(), msg, @@ -1803,7 +1808,7 @@ ); err.span_label(lifetime_ref.span, "undeclared lifetime"); let mut suggests_in_band = false; - let mut suggest_note = true; + let mut suggested_spans = vec![]; for missing in &self.missing_named_lifetime_spots { match missing { MissingLifetimeSpot::Generics(generics) => { @@ -1821,23 +1826,17 @@ suggests_in_band = true; (generics.span, format!("<{}>", lifetime_ref)) }; - if !span.from_expansion() { + if suggested_spans.contains(&span) { + continue; + } + suggested_spans.push(span); + if span.can_be_used_for_suggestions() { err.span_suggestion( span, &format!("consider introducing lifetime `{}` here", lifetime_ref), sugg, Applicability::MaybeIncorrect, ); - } else if suggest_note { - suggest_note = false; // Avoid displaying the same help multiple times. - err.span_label( - span, - &format!( - "lifetime `{}` is missing in item created through this procedural \ - macro", - lifetime_ref, - ), - ); } } MissingLifetimeSpot::HigherRanked { span, span_type } => { @@ -1871,6 +1870,117 @@ err.emit(); } + /// Returns whether to add `'static` lifetime to the suggested lifetime list. + crate fn report_elision_failure( + &mut self, + db: &mut DiagnosticBuilder<'_>, + params: &[ElisionFailureInfo], + ) -> bool { + let mut m = String::new(); + let len = params.len(); + + let elided_params: Vec<_> = + params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); + + let elided_len = elided_params.len(); + + for (i, info) in elided_params.into_iter().enumerate() { + let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = + info; + + db.span_label(span, ""); + let help_name = if let Some(ident) = + parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) + { + format!("`{}`", ident) + } else { + format!("argument {}", index + 1) + }; + + m.push_str( + &(if n == 1 { + help_name + } else { + format!( + "one of {}'s {} {}lifetimes", + help_name, + n, + if have_bound_regions { "free " } else { "" } + ) + })[..], + ); + + if elided_len == 2 && i == 0 { + m.push_str(" or "); + } else if i + 2 == elided_len { + m.push_str(", or "); + } else if i != elided_len - 1 { + m.push_str(", "); + } + } + + if len == 0 { + db.help( + "this function's return type contains a borrowed value, \ + but there is no value for it to be borrowed from", + ); + true + } else if elided_len == 0 { + db.help( + "this function's return type contains a borrowed value with \ + an elided lifetime, but the lifetime cannot be derived from \ + the arguments", + ); + true + } else if elided_len == 1 { + db.help(&format!( + "this function's return type contains a borrowed value, \ + but the signature does not say which {} it is borrowed from", + m + )); + false + } else { + db.help(&format!( + "this function's return type contains a borrowed value, \ + but the signature does not say whether it is borrowed from {}", + m + )); + false + } + } + + crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) { + let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| { + lt.name == hir::LifetimeName::Implicit(true) + }) else { return }; + + let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); + spans.sort(); + let mut spans_dedup = spans.clone(); + spans_dedup.dedup(); + let spans_with_counts: Vec<_> = spans_dedup + .into_iter() + .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count())) + .collect(); + + self.tcx.struct_span_lint_hir( + rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS, + missing_lifetime.hir_id, + spans, + |lint| { + let mut db = lint.build("hidden lifetime parameters in types are deprecated"); + self.add_missing_lifetime_specifiers_label( + &mut db, + spans_with_counts, + &FxHashSet::from_iter([kw::UnderscoreLifetime]), + Vec::new(), + &[], + ); + db.emit() + }, + ); + } + // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const // generics. We are disallowing this until we can decide on how we want to handle non-'static // lifetimes in const generics. See issue #74052 for discussion. @@ -2005,11 +2115,19 @@ let spans_suggs: Vec<_> = formatters .into_iter() .zip(spans_with_counts.iter()) - .filter_map(|(fmt, (span, _))| { - if let Some(formatter) = fmt { Some((formatter, span)) } else { None } + .filter_map(|(formatter, (span, _))| { + if let Some(formatter) = formatter { + Some((*span, formatter(name))) + } else { + None + } }) - .map(|(formatter, span)| (*span, formatter(name))) .collect(); + if spans_suggs.is_empty() { + // If all the spans come from macros, we cannot extract snippets and then + // `formatters` only contains None and `spans_suggs` is empty. + return; + } err.multipart_suggestion_verbose( &format!( "consider using the `{}` lifetime", @@ -2230,7 +2348,7 @@ _ => None, }); } - suggest_existing(err, &name.as_str()[..], suggs); + suggest_existing(err, name.as_str(), suggs); } [] => { let mut suggs = Vec::new(); @@ -2297,7 +2415,9 @@ ); let is_allowed_lifetime = matches!( lifetime_ref.name, - hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore + hir::LifetimeName::Implicit(_) + | hir::LifetimeName::Static + | hir::LifetimeName::Underscore ); if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/lifetimes.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/lifetimes.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/lifetimes.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late/lifetimes.rs 2022-02-23 04:07:21.000000000 +0000 @@ -357,11 +357,11 @@ #[derive(Clone, Debug)] crate struct ElisionFailureInfo { /// Where we can find the argument pattern. - parent: Option, + crate parent: Option, /// The index of the argument in the original definition. - index: usize, - lifetime_count: usize, - have_bound_regions: bool, + crate index: usize, + crate lifetime_count: usize, + crate have_bound_regions: bool, crate span: Span, } @@ -445,7 +445,7 @@ trait_definition_only: bool, with_scope_for_path: bool, ) -> NamedRegionMap { - let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id)); + let item = tcx.hir().expect_item(local_def_id); let mut named_region_map = NamedRegionMap { defs: Default::default(), late_bound: Default::default(), @@ -689,11 +689,11 @@ hir_id: hir::HirId, ) { let name = match fk { - intravisit::FnKind::ItemFn(id, _, _, _) => id.as_str(), - intravisit::FnKind::Method(id, _, _) => id.as_str(), - intravisit::FnKind::Closure => Symbol::intern("closure").as_str(), + intravisit::FnKind::ItemFn(id, _, _, _) => id.name, + intravisit::FnKind::Method(id, _, _) => id.name, + intravisit::FnKind::Closure => sym::closure, }; - let name: &str = &name; + let name = name.as_str(); let span = span!(Level::DEBUG, "visit_fn", name); let _enter = span.enter(); match fk { @@ -923,7 +923,7 @@ } }); match lifetime.name { - LifetimeName::Implicit => { + LifetimeName::Implicit(_) => { // For types like `dyn Foo`, we should // generate a special form of elided. span_bug!(ty.span, "object-lifetime-default expected, not implicit",); @@ -968,7 +968,10 @@ let (generics, bounds) = match opaque_ty.kind { // Named opaque `impl Trait` types are reached via `TyKind::Path`. // This arm is for `impl Trait` in the types of statics, constants and locals. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { intravisit::walk_ty(self, ty); // Elided lifetimes are not allowed in non-return @@ -985,7 +988,7 @@ } // RPIT (return position impl trait) hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(_), + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), ref generics, bounds, .. @@ -1134,7 +1137,7 @@ self.missing_named_lifetime_spots.push((&trait_item.generics).into()); let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir().get_parent_item(trait_item.hir_id())), + Some(tcx.hir().get_parent_did(trait_item.hir_id())), trait_item.hir_id(), &sig.decl, &trait_item.generics, @@ -1203,7 +1206,7 @@ self.missing_named_lifetime_spots.push((&impl_item.generics).into()); let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir().get_parent_item(impl_item.hir_id())), + Some(tcx.hir().get_parent_did(impl_item.hir_id())), impl_item.hir_id(), &sig.decl, &impl_item.generics, @@ -1347,11 +1350,14 @@ this.visit_ty(&ty); } } - GenericParamKind::Const { ref ty, .. } => { + GenericParamKind::Const { ref ty, default } => { let was_in_const_generic = this.is_in_const_generic; this.is_in_const_generic = true; walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); + if let Some(default) = default { + this.visit_body(this.tcx.hir().body(default.body)); + } this.is_in_const_generic = was_in_const_generic; } } @@ -1695,7 +1701,11 @@ hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) => { let result = object_lifetime_defaults_for_item(tcx, generics); @@ -2002,7 +2012,7 @@ } }; - let mut def_ids: Vec<_> = defined_by + let def_ids: Vec<_> = defined_by .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) @@ -2013,9 +2023,6 @@ }) .collect(); - // ensure that we issue lints in a repeatable order - def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); - 'lifetimes: for def_id in def_ids { debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id); @@ -2067,7 +2074,7 @@ .. }) = self.tcx.hir().get(parent_hir_id) { - if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) { continue 'lifetimes; } // We want to do this only if the liftime identifier is already defined @@ -2176,7 +2183,7 @@ /// ordering is not important there. fn visit_early_late( &mut self, - parent_id: Option, + parent_id: Option, hir_id: hir::HirId, decl: &'tcx hir::FnDecl<'tcx>, generics: &'tcx hir::Generics<'tcx>, @@ -2534,8 +2541,8 @@ GenericParamDefKind::Type { object_lifetime_default, .. } => { Some(object_lifetime_default) } - GenericParamDefKind::Lifetime - | GenericParamDefKind::Const { .. } => None, + GenericParamDefKind::Const { .. } => Some(Set1::Empty), + GenericParamDefKind::Lifetime => None, }) .collect() }) @@ -2562,12 +2569,11 @@ } GenericArg::Const(ct) => { self.visit_anon_const(&ct.value); + i += 1; } GenericArg::Infer(inf) => { self.visit_id(inf.hir_id); - if inf.kind.is_type() { - i += 1; - } + i += 1; } } } @@ -2758,7 +2764,7 @@ Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => { if let hir::ItemKind::Trait(.., ref trait_items) = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind { assoc_item_kind = trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind); @@ -2771,7 +2777,7 @@ Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => { if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind { impl_self = Some(self_ty); assoc_item_kind = @@ -3057,9 +3063,9 @@ let error = loop { match *scope { // Do not assign any resolution, it will be inferred. - Scope::Body { .. } => return, + Scope::Body { .. } => break Ok(()), - Scope::Root => break None, + Scope::Root => break Err(None), Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions @@ -3076,50 +3082,54 @@ scope = s; } - Scope::Elision { ref elide, ref s, .. } => { - let lifetime = match *elide { - Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { - for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(named_late_bound_vars, counter) - .shifted(late_depth); + Scope::Elision { + elide: Elide::FreshLateAnon(named_late_bound_vars, ref counter), + .. + } => { + for lifetime_ref in lifetime_refs { + let lifetime = + Region::late_anon(named_late_bound_vars, counter).shifted(late_depth); - self.insert_lifetime(lifetime_ref, lifetime); - } - return; - } - Elide::Exact(l) => l.shifted(late_depth), - Elide::Error(ref e) => { - let mut scope = s; - loop { - match scope { - Scope::Binder { ref lifetimes, s, .. } => { - // Collect named lifetimes for suggestions. - for name in lifetimes.keys() { - if let hir::ParamName::Plain(name) = name { - lifetime_names.insert(name.name); - lifetime_spans.push(name.span); - } - } - scope = s; - } - Scope::ObjectLifetimeDefault { ref s, .. } - | Scope::Elision { ref s, .. } - | Scope::TraitRefBoundary { ref s, .. } => { - scope = s; + self.insert_lifetime(lifetime_ref, lifetime); + } + break Ok(()); + } + + Scope::Elision { elide: Elide::Exact(l), .. } => { + let lifetime = l.shifted(late_depth); + for lifetime_ref in lifetime_refs { + self.insert_lifetime(lifetime_ref, lifetime); + } + break Ok(()); + } + + Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => { + let mut scope = s; + loop { + match scope { + Scope::Binder { ref lifetimes, s, .. } => { + // Collect named lifetimes for suggestions. + for name in lifetimes.keys() { + if let hir::ParamName::Plain(name) = name { + lifetime_names.insert(name.name); + lifetime_spans.push(name.span); } - _ => break, } + scope = s; } - break Some(&e[..]); + Scope::ObjectLifetimeDefault { ref s, .. } + | Scope::Elision { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { + scope = s; + } + _ => break, } - Elide::Forbid => break None, - }; - for lifetime_ref in lifetime_refs { - self.insert_lifetime(lifetime_ref, lifetime); } - return; + break Err(Some(&e[..])); } + Scope::Elision { elide: Elide::Forbid, .. } => break Err(None), + Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { @@ -3128,6 +3138,14 @@ } }; + let error = match error { + Ok(()) => { + self.report_elided_lifetime_in_ty(lifetime_refs); + return; + } + Err(error) => error, + }; + // If we specifically need the `scope_for_path` map, then we're in the // diagnostic pass and we don't want to emit more errors. if self.map.scope_for_path.is_some() { @@ -3166,84 +3184,6 @@ err.emit(); } - fn report_elision_failure( - &mut self, - db: &mut DiagnosticBuilder<'_>, - params: &[ElisionFailureInfo], - ) -> bool /* add `'static` lifetime to lifetime list */ { - let mut m = String::new(); - let len = params.len(); - - let elided_params: Vec<_> = - params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); - - let elided_len = elided_params.len(); - - for (i, info) in elided_params.into_iter().enumerate() { - let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = - info; - - db.span_label(span, ""); - let help_name = if let Some(ident) = - parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) - { - format!("`{}`", ident) - } else { - format!("argument {}", index + 1) - }; - - m.push_str( - &(if n == 1 { - help_name - } else { - format!( - "one of {}'s {} {}lifetimes", - help_name, - n, - if have_bound_regions { "free " } else { "" } - ) - })[..], - ); - - if elided_len == 2 && i == 0 { - m.push_str(" or "); - } else if i + 2 == elided_len { - m.push_str(", or "); - } else if i != elided_len - 1 { - m.push_str(", "); - } - } - - if len == 0 { - db.help( - "this function's return type contains a borrowed value, \ - but there is no value for it to be borrowed from", - ); - true - } else if elided_len == 0 { - db.help( - "this function's return type contains a borrowed value with \ - an elided lifetime, but the lifetime cannot be derived from \ - the arguments", - ); - true - } else if elided_len == 1 { - db.help(&format!( - "this function's return type contains a borrowed value, \ - but the signature does not say which {} it is borrowed from", - m - )); - false - } else { - db.help(&format!( - "this function's return type contains a borrowed value, \ - but the signature does not say whether it is borrowed from {}", - m - )); - false - } - } - fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; @@ -3348,7 +3288,7 @@ )) .emit(); } - hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => { + hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => { self.resolve_lifetime_ref(lt); } hir::LifetimeName::ImplicitObjectLifetimeDefault => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/late.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1603,10 +1603,13 @@ pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, ) { + // We walk the pattern before declaring the pattern's inner bindings, + // so that we avoid resolving a literal expression to a binding defined + // by the pattern. + visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: self.check_consistent_bindings_top(pat); - visit::walk_pat(self, pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. @@ -2376,7 +2379,9 @@ ExprKind::While(ref cond, ref block, label) => { self.with_resolved_label(label, expr.id, |this| { this.with_rib(ValueNS, NormalRibKind, |this| { + let old = this.diagnostic_metadata.in_if_condition.replace(cond); this.visit_expr(cond); + this.diagnostic_metadata.in_if_condition = old; this.visit_block(block); }) }); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,8 +13,6 @@ #![feature(drain_filter)] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(let_else)] #![feature(never_type)] #![feature(nll)] @@ -70,7 +68,7 @@ use std::cell::{Cell, RefCell}; use std::collections::{BTreeMap, BTreeSet}; use std::ops::ControlFlow; -use std::{cmp, fmt, iter, ptr}; +use std::{cmp, fmt, iter, mem, ptr}; use tracing::debug; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; @@ -1396,7 +1394,7 @@ .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .collect(), lint_buffer: LintBuffer::default(), - next_node_id: NodeId::from_u32(1), + next_node_id: CRATE_NODE_ID, node_id_to_def_id, def_id_to_node_id, placeholder_field_indices: Default::default(), @@ -1430,13 +1428,9 @@ } pub fn next_node_id(&mut self) -> NodeId { - let next = self - .next_node_id - .as_usize() - .checked_add(1) - .expect("input too large; ran out of NodeIds"); - self.next_node_id = ast::NodeId::from_usize(next); - self.next_node_id + let next = + self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds"); + mem::replace(&mut self.next_node_id, ast::NodeId::from_u32(next)) } pub fn lint_buffer(&mut self) -> &mut LintBuffer { @@ -3288,7 +3282,9 @@ Some(binding) } else { let crate_id = if !speculative { - self.crate_loader.process_path_extern(ident.name, ident.span) + let Some(crate_id) = + self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); }; + crate_id } else { self.crate_loader.maybe_process_path_extern(ident.name)? }; @@ -3422,27 +3418,21 @@ return v.clone(); } - let parse_attrs = || { - let attrs = self.cstore().item_attrs(def_id, self.session); - let attr = - attrs.iter().find(|a| a.has_name(sym::rustc_legacy_const_generics))?; - let mut ret = vec![]; - for meta in attr.meta_item_list()? { - match meta.literal()?.kind { - LitKind::Int(a, _) => { - ret.push(a as usize); - } - _ => panic!("invalid arg index"), - } + let attr = self + .cstore() + .item_attrs_untracked(def_id, self.session) + .into_iter() + .find(|a| a.has_name(sym::rustc_legacy_const_generics))?; + let mut ret = Vec::new(); + for meta in attr.meta_item_list()? { + match meta.literal()?.kind { + LitKind::Int(a, _) => ret.push(a as usize), + _ => panic!("invalid arg index"), } - Some(ret) - }; - - // Cache the lookup to avoid parsing attributes for an iterm - // multiple times. - let ret = parse_attrs(); - self.legacy_const_generic_args.insert(def_id, ret.clone()); - return ret; + } + // Cache the lookup to avoid parsing attributes for an iterm multiple times. + self.legacy_const_generic_args.insert(def_id, Some(ret.clone())); + return Some(ret); } } None @@ -3484,7 +3474,7 @@ if Ident::with_dummy_span(*name).is_raw_guess() { result.push_str("r#"); } - result.push_str(&name.as_str()); + result.push_str(name.as_str()); } result } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/macros.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/macros.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/macros.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_resolve/src/macros.rs 2022-02-23 04:07:21.000000000 +0000 @@ -105,7 +105,7 @@ path_str.push_str("::"); } if segment.ident.name != kw::PathRoot { - path_str.push_str(&segment.ident.as_str()) + path_str.push_str(segment.ident.as_str()) } } Symbol::intern(&path_str) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/dump_visitor.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/dump_visitor.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/dump_visitor.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/dump_visitor.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1326,12 +1326,18 @@ } intravisit::walk_qpath(self, path, t.hir_id, t.span); } - hir::TyKind::Array(ref ty, ref anon_const) => { + hir::TyKind::Array(ref ty, ref length) => { self.visit_ty(ty); let map = self.tcx.hir(); - self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { - v.visit_expr(&map.body(anon_const.body).value) - }); + match length { + // FIXME(generic_arg_infer): We probably want to + // output the inferred type here? :shrug: + hir::ArrayLen::Infer(..) => {} + hir::ArrayLen::Body(anon_const) => self + .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { + v.visit_expr(&map.body(anon_const.body).value) + }), + } } hir::TyKind::OpaqueDef(item_id, _) => { let item = self.tcx.hir().item(item_id); @@ -1390,12 +1396,18 @@ v.visit_expr(&body.value) }); } - hir::ExprKind::Repeat(ref expr, ref anon_const) => { + hir::ExprKind::Repeat(ref expr, ref length) => { self.visit_expr(expr); let map = self.tcx.hir(); - self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { - v.visit_expr(&map.body(anon_const.body).value) - }); + match length { + // FIXME(generic_arg_infer): We probably want to + // output the inferred type here? :shrug: + hir::ArrayLen::Infer(..) => {} + hir::ArrayLen::Body(anon_const) => self + .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { + v.visit_expr(&map.body(anon_const.body).value) + }), + } } // In particular, we take this branch for call and path expressions, // where we'll index the idents involved just by continuing to walk. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -825,7 +825,7 @@ for attr in attrs { if let Some(val) = attr.doc_str() { // FIXME: Should save-analysis beautify doc strings itself or leave it to users? - result.push_str(&beautify_doc_string(val).as_str()); + result.push_str(beautify_doc_string(val).as_str()); result.push('\n'); } } @@ -1036,7 +1036,7 @@ // Helper function to escape quotes in a string fn escape(s: String) -> String { - s.replace("\"", "\"\"") + s.replace('\"', "\"\"") } // Helper function to determine if a span came from a diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/sig.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/sig.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/sig.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_save_analysis/src/sig.rs 2022-02-23 04:07:21.000000000 +0000 @@ -286,7 +286,7 @@ refs: vec![SigElement { id, start, end }], }) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => { Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name()))) } hir::TyKind::TraitObject(bounds, ..) => { @@ -310,9 +310,9 @@ let nested = bounds_to_string(&bounds); Ok(text_sig(nested)) } - hir::TyKind::Array(ref ty, ref anon_const) => { + hir::TyKind::Array(ref ty, ref length) => { let nested_ty = ty.make(offset + 1, id, scx)?; - let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " "); + let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " "); let text = format!("[{}; {}]", nested_ty.text, expr); Ok(replace_text(nested_ty, text)) } @@ -616,7 +616,7 @@ if let hir::GenericParamKind::Const { .. } = param.kind { param_text.push_str("const "); } - param_text.push_str(¶m.name.ident().as_str()); + param_text.push_str(param.name.ident().as_str()); defs.push(SigElement { id: id_from_hir_id(param.hir_id, scx), start: offset + text.len(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/json.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/json.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/json.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/json.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2320,12 +2320,12 @@ let name = match self.pop() { Json::String(s) => s, Json::Object(mut o) => { - let n = match o.remove(&"variant".to_owned()) { + let n = match o.remove("variant") { Some(Json::String(s)) => s, Some(val) => return Err(ExpectedError("String".to_owned(), val.to_string())), None => return Err(MissingFieldError("variant".to_owned())), }; - match o.remove(&"fields".to_string()) { + match o.remove("fields") { Some(Json::Array(l)) => { self.stack.extend(l.into_iter().rev()); } @@ -2365,7 +2365,7 @@ { let mut obj = expect!(self.pop(), Object)?; - let value = match obj.remove(&name.to_string()) { + let value = match obj.remove(name) { None => { // Add a Null and try to parse it as an Option<_> // to get None as a default value. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/opaque.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/opaque.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/opaque.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_serialize/src/opaque.rs 2022-02-23 04:07:21.000000000 +0000 @@ -55,6 +55,13 @@ }}; } +/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string. +/// This way we can skip validation and still be relatively sure that deserialization +/// did not desynchronize. +/// +/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout +const STR_SENTINEL: u8 = 0xC1; + impl serialize::Encoder for Encoder { type Error = !; @@ -85,7 +92,8 @@ #[inline] fn emit_u16(&mut self, v: u16) -> EncodeResult { - write_leb128!(self, v, u16, write_u16_leb128) + self.data.extend_from_slice(&v.to_le_bytes()); + Ok(()) } #[inline] @@ -116,7 +124,8 @@ #[inline] fn emit_i16(&mut self, v: i16) -> EncodeResult { - write_leb128!(self, v, i16, write_i16_leb128) + self.data.extend_from_slice(&v.to_le_bytes()); + Ok(()) } #[inline] @@ -150,7 +159,8 @@ #[inline] fn emit_str(&mut self, v: &str) -> EncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()) + self.emit_raw_bytes(v.as_bytes())?; + self.emit_u8(STR_SENTINEL) } #[inline] @@ -438,7 +448,7 @@ #[inline] fn emit_u16(&mut self, v: u16) -> FileEncodeResult { - file_encoder_write_leb128!(self, v, u16, write_u16_leb128) + self.write_all(&v.to_le_bytes()) } #[inline] @@ -468,13 +478,12 @@ #[inline] fn emit_i16(&mut self, v: i16) -> FileEncodeResult { - file_encoder_write_leb128!(self, v, i16, write_i16_leb128) + self.write_all(&v.to_le_bytes()) } #[inline] fn emit_i8(&mut self, v: i8) -> FileEncodeResult { - let as_u8: u8 = unsafe { std::mem::transmute(v) }; - self.emit_u8(as_u8) + self.emit_u8(v as u8) } #[inline] @@ -502,7 +511,8 @@ #[inline] fn emit_str(&mut self, v: &str) -> FileEncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()) + self.emit_raw_bytes(v.as_bytes())?; + self.emit_u8(STR_SENTINEL) } #[inline] @@ -582,7 +592,10 @@ #[inline] fn read_u16(&mut self) -> Result { - read_leb128!(self, read_u16_leb128) + let bytes = [self.data[self.position], self.data[self.position + 1]]; + let value = u16::from_le_bytes(bytes); + self.position += 2; + Ok(value) } #[inline] @@ -614,7 +627,10 @@ #[inline] fn read_i16(&mut self) -> Result { - read_leb128!(self, read_i16_leb128) + let bytes = [self.data[self.position], self.data[self.position + 1]]; + let value = i16::from_le_bytes(bytes); + self.position += 2; + Ok(value) } #[inline] @@ -656,8 +672,12 @@ #[inline] fn read_str(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; - let s = std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); - self.position += len; + let sentinel = self.data[self.position + len]; + assert!(sentinel == STR_SENTINEL); + let s = unsafe { + std::str::from_utf8_unchecked(&self.data[self.position..self.position + len]) + }; + self.position += len + 1; Ok(Cow::Borrowed(s)) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/config.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/config.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/config.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/config.rs 2022-02-23 04:07:21.000000000 +0000 @@ -231,6 +231,37 @@ Full, } +/// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split +/// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform +/// uses DWARF for debug-information. +/// +/// Some debug-information requires link-time relocation and some does not. LLVM can partition +/// the debuginfo into sections depending on whether or not it requires link-time relocation. Split +/// DWARF provides a mechanism which allows the linker to skip the sections which don't require +/// link-time relocation - either by putting those sections in DWARF object files, or by keeping +/// them in the object file in such a way that the linker will skip them. +#[derive(Clone, Copy, Debug, PartialEq, Hash)] +pub enum SplitDwarfKind { + /// Sections which do not require relocation are written into object file but ignored by the + /// linker. + Single, + /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file + /// which is ignored by the linker. + Split, +} + +impl FromStr for SplitDwarfKind { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "single" => SplitDwarfKind::Single, + "split" => SplitDwarfKind::Split, + _ => return Err(()), + }) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[derive(Encodable, Decodable)] pub enum OutputType { @@ -378,7 +409,7 @@ self.0.len() } - // Returns `true` if any of the output types require codegen or linking. + /// Returns `true` if any of the output types require codegen or linking. pub fn should_codegen(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -391,7 +422,7 @@ }) } - // Returns `true` if any of the output types require linking. + /// Returns `true` if any of the output types require linking. pub fn should_link(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -681,18 +712,23 @@ pub fn split_dwarf_path( &self, split_debuginfo_kind: SplitDebuginfo, + split_dwarf_kind: SplitDwarfKind, cgu_name: Option<&str>, ) -> Option { let obj_out = self.temp_path(OutputType::Object, cgu_name); let dwo_out = self.temp_path_dwo(cgu_name); - match split_debuginfo_kind { - SplitDebuginfo::Off => None, + match (split_debuginfo_kind, split_dwarf_kind) { + (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes // (pointing at the path which is being determined here). Use the path to the current // object file. - SplitDebuginfo::Packed => Some(obj_out), + (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => { + Some(obj_out) + } // Split mode emits the DWARF into a different file, use that path. - SplitDebuginfo::Unpacked => Some(dwo_out), + (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => { + Some(dwo_out) + } } } } @@ -746,6 +782,7 @@ edition: DEFAULT_EDITION, json_artifact_notifications: false, json_unused_externs: false, + json_future_incompat: false, pretty: None, working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()), } @@ -780,6 +817,10 @@ }, } } + + pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { + self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) + } } impl DebuggingOptions { @@ -793,10 +834,6 @@ deduplicate_diagnostics: self.deduplicate_diagnostics, } } - - pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) - } } // The type of entry function, so users can have their own entry functions @@ -820,6 +857,18 @@ impl_stable_hash_via_hash!(CrateType); +impl CrateType { + /// When generated, is this crate type an archive? + pub fn is_archive(&self) -> bool { + match *self { + CrateType::Rlib | CrateType::Staticlib => true, + CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { + false + } + } + } +} + #[derive(Clone, Hash, Debug, PartialEq, Eq)] pub enum Passes { Some(Vec), @@ -833,6 +882,13 @@ Passes::All => false, } } + + pub fn extend(&mut self, passes: impl IntoIterator) { + match *self { + Passes::Some(ref mut v) => v.extend(passes), + Passes::All => {} + } + } } pub const fn default_lib_output() -> CrateType { @@ -872,7 +928,7 @@ ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_abi, Some(Symbol::intern(abi)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); - if sess.target.has_elf_tls { + if sess.target.has_thread_local { ret.insert((sym::target_thread_local, None)); } for (i, align) in [ @@ -1205,7 +1261,7 @@ if lint_name == "help" { describe_lints = true; } else { - lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level)); + lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level)); } } } @@ -1250,6 +1306,7 @@ pub json_rendered: HumanReadableErrorType, pub json_artifact_notifications: bool, pub json_unused_externs: bool, + pub json_future_incompat: bool, } /// Parse the `--json` flag. @@ -1262,6 +1319,7 @@ let mut json_color = ColorConfig::Never; let mut json_artifact_notifications = false; let mut json_unused_externs = false; + let mut json_future_incompat = false; for option in matches.opt_strs("json") { // For now conservatively forbid `--color` with `--json` since `--json` // won't actually be emitting any colors and anything colorized is @@ -1279,6 +1337,7 @@ "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, "artifacts" => json_artifact_notifications = true, "unused-externs" => json_unused_externs = true, + "future-incompat" => json_future_incompat = true, s => early_error( ErrorOutputType::default(), &format!("unknown `--json` option `{}`", s), @@ -1291,6 +1350,7 @@ json_rendered: json_rendered(json_color), json_artifact_notifications, json_unused_externs, + json_future_incompat, } } @@ -1723,7 +1783,7 @@ ) -> (NativeLibKind, Option) { let mut verbatim = None; for modifier in modifiers.split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-'][..]) { + let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => early_error( error_format, @@ -2004,14 +2064,18 @@ let edition = parse_crate_edition(matches); - let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } = - parse_json(matches); + let JsonConfig { + json_rendered, + json_artifact_notifications, + json_unused_externs, + json_future_incompat, + } = parse_json(matches); let error_format = parse_error_format(matches, color, json_rendered); let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(error_format, &e[..])); + .unwrap_or_else(|e| early_error(error_format, &e)); let mut debugging_opts = DebuggingOptions::build(matches, error_format); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -2038,7 +2102,12 @@ check_thread_count(&debugging_opts, error_format); - let incremental = cg.incremental.as_ref().map(PathBuf::from); + let incremental = + if std::env::var_os("RUSTC_FORCE_INCREMENTAL").map(|v| v == "1").unwrap_or(false) { + cg.incremental.as_ref().map(PathBuf::from) + } else { + None + }; let assert_incr_state = parse_assert_incr_state(&debugging_opts.assert_incr_state, error_format); @@ -2076,6 +2145,34 @@ ); } + // Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes + // precedence. + match (cg.symbol_mangling_version, debugging_opts.symbol_mangling_version) { + (Some(smv_c), Some(smv_z)) if smv_c != smv_z => { + early_error( + error_format, + "incompatible values passed for `-C symbol-mangling-version` \ + and `-Z symbol-mangling-version`", + ); + } + (Some(SymbolManglingVersion::V0), _) => {} + (Some(_), _) if !debugging_opts.unstable_options => { + early_error( + error_format, + "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`", + ); + } + (None, None) => {} + (None, smv) => { + early_warn( + error_format, + "`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`", + ); + cg.symbol_mangling_version = smv; + } + _ => {} + } + if debugging_opts.instrument_coverage.is_some() && debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off) { @@ -2087,19 +2184,17 @@ ); } - // `-Z instrument-coverage` implies `-Z symbol-mangling-version=v0` - to ensure consistent + // `-Z instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over // multiple runs, including some changes to source code; so mangled names must be consistent // across compilations. - match debugging_opts.symbol_mangling_version { - None => { - debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0); - } + match cg.symbol_mangling_version { + None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0), Some(SymbolManglingVersion::Legacy) => { early_warn( error_format, "-Z instrument-coverage requires symbol mangling version `v0`, \ - but `-Z symbol-mangling-version=legacy` was specified", + but `-C symbol-mangling-version=legacy` was specified", ); } Some(SymbolManglingVersion::V0) => {} @@ -2135,7 +2230,7 @@ let mut search_paths = vec![]; for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); + search_paths.push(SearchPath::from_cli_opt(&s, error_format)); } let libs = parse_libs(matches, error_format); @@ -2241,6 +2336,7 @@ edition, json_artifact_notifications, json_unused_externs, + json_future_incompat, pretty, working_dir, } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/cstore.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/cstore.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/cstore.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/cstore.rs 2022-02-23 04:07:21.000000000 +0000 @@ -201,6 +201,12 @@ index_guess: u32, hash: ExpnHash, ) -> ExpnId; + + /// Imports all `SourceFile`s from the given crate into the current session. + /// This normally happens automatically when we decode a `Span` from + /// that crate's metadata - however, the incr comp cache needs + /// to trigger this manually when decoding a foreign `Span` + fn import_source_files(&self, sess: &Session, cnum: CrateNum); } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/filesearch.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/filesearch.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/filesearch.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/filesearch.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,6 +4,7 @@ use std::env; use std::fs; +use std::iter::FromIterator; use std::path::{Path, PathBuf}; use crate::search_paths::{PathKind, SearchPath, SearchPathFile}; @@ -91,8 +92,7 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple); - std::array::IntoIter::new([sysroot, Path::new(&rustlib_path), Path::new("lib")]) - .collect::() + PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")]) } /// This function checks if sysroot is found using env::args().next(), and if it diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/options.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/options.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/options.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/options.rs 2022-02-23 04:07:21.000000000 +0000 @@ -101,6 +101,29 @@ ); } +impl Options { + pub fn mir_opt_level(&self) -> usize { + self.debugging_opts + .mir_opt_level + .unwrap_or_else(|| if self.optimize != OptLevel::No { 2 } else { 1 }) + } + + pub fn instrument_coverage(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + != InstrumentCoverage::Off + } + + pub fn instrument_coverage_except_unused_generics(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + == InstrumentCoverage::ExceptUnusedGenerics + } + + pub fn instrument_coverage_except_unused_functions(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + == InstrumentCoverage::ExceptUnusedFunctions + } +} + top_level_options!( /// The top-level command-line options struct. /// @@ -205,6 +228,9 @@ /// `true` if we're emitting a JSON blob containing the unused externs json_unused_externs: bool [UNTRACKED], + /// `true` if we're emitting a JSON job containg a future-incompat report for lints + json_future_incompat: bool [TRACKED], + pretty: Option [UNTRACKED], /// The (potentially remapped) working directory @@ -309,7 +335,7 @@ Some((k, v)) => (k.to_string(), Some(v)), }; - let option_to_lookup = key.replace("-", "_"); + let option_to_lookup = key.replace('-', "_"); match descrs.iter().find(|(name, ..)| *name == option_to_lookup) { Some((_, setter, type_desc, _)) => { if !setter(&mut op, value) { @@ -386,6 +412,8 @@ pub const parse_wasi_exec_model: &str = "either `command` or `reactor`"; pub const parse_split_debuginfo: &str = "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; + pub const parse_split_dwarf_kind: &str = + "one of supported split dwarf modes (`split` or `single`)"; pub const parse_gcc_ld: &str = "one of: no value, `lld`"; pub const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; @@ -567,7 +595,7 @@ v => { let mut passes = vec![]; if parse_list(&mut passes, v) { - *slot = Passes::Some(passes); + slot.extend(passes); true } else { false @@ -913,6 +941,14 @@ true } + crate fn parse_split_dwarf_kind(slot: &mut SplitDwarfKind, v: Option<&str>) -> bool { + match v.and_then(|s| SplitDwarfKind::from_str(s).ok()) { + Some(e) => *slot = e, + _ => return false, + } + true + } + crate fn parse_gcc_ld(slot: &mut Option, v: Option<&str>) -> bool { match v { None => *slot = None, @@ -1029,6 +1065,9 @@ "how to handle split-debuginfo, a platform-specific option"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), + symbol_mangling_version: Option = (None, + parse_symbol_mangling_version, [TRACKED], + "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], @@ -1124,8 +1163,6 @@ computed `block` spans (one span encompassing a block's terminator and \ all statements). If `-Z instrument-coverage` is also enabled, create \ an additional `.html` file showing the computed coverage spans."), - emit_future_incompat_report: bool = (false, parse_bool, [UNTRACKED], - "emits a future-incompatibility report for lints (RFC 2834)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), fewer_names: Option = (None, parse_opt_bool, [TRACKED], @@ -1173,7 +1210,7 @@ instrument_coverage: Option = (None, parse_instrument_coverage, [TRACKED], "instrument the generated code to support LLVM source-based code coverage \ reports (note, the compiler build config must include `profiler = true`); \ - implies `-Z symbol-mangling-version=v0`. Optional values are: + implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) `=except-unused-generics` `=except-unused-functions` @@ -1297,6 +1334,8 @@ "print some statistics about the query system (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), + layout_seed: Option = (None, parse_opt_number, [TRACKED], + "seed layout randomization"), relax_elf_relocations: Option = (None, parse_opt_bool, [TRACKED], "whether ELF relocations can be relaxed"), relro_level: Option = (None, parse_relro_level, [TRACKED], @@ -1344,6 +1383,14 @@ "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), + split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED], + "split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) + (default: `split`) + + `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) + file which is ignored by the linker + `single`: sections which do not require relocation are written into object file but ignored + by the linker"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], "provide minimal debug info in the object/executable to facilitate online \ symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/output.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/output.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/output.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/output.rs 2022-02-23 04:07:21.000000000 +0000 @@ -60,7 +60,7 @@ if let Some(ref s) = sess.opts.crate_name { if let Some((attr, name)) = attr_crate_name { - if name.as_str() != *s { + if name.as_str() != s { let msg = format!( "`--crate-name` and `#[crate_name]` are \ required to match, but `{}` != `{}`", @@ -85,7 +85,7 @@ ); sess.err(&msg); } else { - return validate(s.replace("-", "_"), None); + return validate(s.replace('-', "_"), None); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/session.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/session.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/session.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_session/src/session.rs 2022-02-23 04:07:21.000000000 +0000 @@ -280,7 +280,7 @@ } fn emit_future_breakage(&self) { - if !self.opts.debugging_opts.emit_future_incompat_report { + if !self.opts.json_future_incompat { return; } @@ -562,10 +562,7 @@ self.opts.debugging_opts.binary_dep_depinfo } pub fn mir_opt_level(&self) -> usize { - self.opts - .debugging_opts - .mir_opt_level - .unwrap_or_else(|| if self.opts.optimize != config::OptLevel::No { 2 } else { 1 }) + self.opts.mir_opt_level() } /// Gets the features enabled for the current compilation session. @@ -795,12 +792,11 @@ /// Returns a list of directories where target-specific tool binaries are located. pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple()); - let p = std::array::IntoIter::new([ + let p = PathBuf::from_iter([ Path::new(&self.sysroot), Path::new(&rustlib_path), Path::new("bin"), - ]) - .collect::(); + ]); if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } } @@ -1047,18 +1043,15 @@ } pub fn instrument_coverage(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - != config::InstrumentCoverage::Off + self.opts.instrument_coverage() } pub fn instrument_coverage_except_unused_generics(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - == config::InstrumentCoverage::ExceptUnusedGenerics + self.opts.instrument_coverage_except_unused_generics() } pub fn instrument_coverage_except_unused_functions(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - == config::InstrumentCoverage::ExceptUnusedFunctions + self.opts.instrument_coverage_except_unused_functions() } pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/def_id.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/def_id.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/def_id.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/def_id.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::borrow::Borrow; use std::fmt; +use std::hash::{Hash, Hasher}; rustc_index::newtype_index! { pub struct CrateNum { @@ -126,14 +127,17 @@ } } -/// A [StableCrateId] is a 64 bit hash of the crate name combined with all -/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to -/// [DefId]. It is stable across compilation sessions. +/// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all +/// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to +/// [`DefId`]. It is stable across compilation sessions. /// -/// Since the ID is a hash value there is a (very small) chance that two crates -/// end up with the same [StableCrateId]. The compiler will check for such +/// Since the ID is a hash value, there is a small chance that two crates +/// end up with the same [`StableCrateId`]. The compiler will check for such /// collisions when loading crates and abort compilation in order to avoid /// further trouble. +/// +/// For more information on the possibility of hash collisions in rustc, +/// see the discussion in [`DefId`]. #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] #[derive(HashStable_Generic, Encodable, Decodable)] pub struct StableCrateId(pub(crate) u64); @@ -146,13 +150,10 @@ /// Computes the stable ID for a crate with the given name and /// `-Cmetadata` arguments. pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { - use std::hash::Hash; - use std::hash::Hasher; - let mut hasher = StableHasher::new(); crate_name.hash(&mut hasher); - // We don't want the stable crate id to dependent on the order + // We don't want the stable crate ID to depend on the order of // -C metadata arguments, so sort them: metadata.sort(); // Every distinct -C metadata value is only incorporated once: @@ -171,6 +172,18 @@ // linking against a library of the same name, if this is an executable. hasher.write(if is_exe { b"exe" } else { b"lib" }); + // Also incorporate the rustc version. Otherwise, with -Zsymbol-mangling-version=v0 + // and no -Cmetadata, symbols from the same crate compiled with different versions of + // rustc are named the same. + // + // RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER is used to inject rustc version information + // during testing. + if let Some(val) = std::env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + hasher.write(val.to_string_lossy().into_owned().as_bytes()) + } else { + hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes()); + } + StableCrateId(hasher.finish()) } } @@ -205,10 +218,38 @@ /// index and a def index. /// /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] +// On below-64 bit systems we can simply use the derived `Hash` impl +#[cfg_attr(not(target_pointer_width = "64"), derive(Hash))] +// Note that the order is essential here, see below why pub struct DefId { - pub krate: CrateNum, pub index: DefIndex, + pub krate: CrateNum, +} + +// On 64-bit systems, we can hash the whole `DefId` as one `u64` instead of two `u32`s. This +// improves performance without impairing `FxHash` quality. So the below code gets compiled to a +// noop on little endian systems because the memory layout of `DefId` is as follows: +// +// ``` +// +-1--------------31-+-32-------------63-+ +// ! index ! krate ! +// +-------------------+-------------------+ +// ``` +// +// The order here has direct impact on `FxHash` quality because we have far more `DefIndex` per +// crate than we have `Crate`s within one compilation. Or in other words, this arrangement puts +// more entropy in the low bits than the high bits. The reason this matters is that `FxHash`, which +// is used throughout rustc, has problems distributing the entropy from the high bits, so reversing +// the order would lead to a large number of collisions and thus far worse performance. +// +// On 64-bit big-endian systems, this compiles to a 64-bit rotation by 32 bits, which is still +// faster than another `FxHash` round. +#[cfg(target_pointer_width = "64")] +impl Hash for DefId { + fn hash(&self, h: &mut H) { + (((self.krate.as_u32() as u64) << 32) | (self.index.as_u32() as u64)).hash(h) + } } impl DefId { @@ -275,17 +316,23 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); -/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since +/// A `LocalDefId` is equivalent to a `DefId` with `krate == LOCAL_CRATE`. Since /// we encode this information in the type, we can ensure at compile time that -/// no DefIds from upstream crates get thrown into the mix. There are quite a -/// few cases where we know that only DefIds from the local crate are expected -/// and a DefId from a different crate would signify a bug somewhere. This -/// is when LocalDefId comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +/// no `DefId`s from upstream crates get thrown into the mix. There are quite a +/// few cases where we know that only `DefId`s from the local crate are expected; +/// a `DefId` from a different crate would signify a bug somewhere. This +/// is when `LocalDefId` comes in handy. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct LocalDefId { pub local_def_index: DefIndex, } +// To ensure correctness of incremental compilation, +// `LocalDefId` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for LocalDefId {} +impl !PartialOrd for LocalDefId {} + pub const CRATE_DEF_ID: LocalDefId = LocalDefId { local_def_index: CRATE_DEF_INDEX }; impl Idx for LocalDefId { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/hygiene.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/hygiene.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/hygiene.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/hygiene.rs 2022-02-23 04:07:21.000000000 +0000 @@ -264,7 +264,15 @@ HygieneData::with(|data| data.expn_data(self).clone()) } + #[inline] pub fn is_descendant_of(self, ancestor: ExpnId) -> bool { + // a few "fast path" cases to avoid locking HygieneData + if ancestor == ExpnId::root() || ancestor == self { + return true; + } + if ancestor.krate != self.krate { + return false; + } HygieneData::with(|data| data.is_descendant_of(self, ancestor)) } @@ -376,13 +384,22 @@ } fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool { - while expn_id != ancestor { + // a couple "fast path" cases to avoid traversing parents in the loop below + if ancestor == ExpnId::root() { + return true; + } + if expn_id.krate != ancestor.krate { + return false; + } + loop { + if expn_id == ancestor { + return true; + } if expn_id == ExpnId::root() { return false; } expn_id = self.expn_data(expn_id).parent; } - true } fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { @@ -1223,6 +1240,7 @@ data: ExpnData, hash: ExpnHash, ) -> ExpnId { + debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate); let expn_id = ExpnId { krate, local_id }; HygieneData::with(|hygiene_data| { let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lev_distance.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lev_distance.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lev_distance.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lev_distance.rs 2022-02-23 04:07:21.000000000 +0000 @@ -55,7 +55,7 @@ lookup: Symbol, dist: Option, ) -> Option { - let lookup = &lookup.as_str(); + let lookup = lookup.as_str(); let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); // Priority of matches: @@ -70,7 +70,7 @@ let levenshtein_match = name_vec .iter() .filter_map(|&name| { - let dist = lev_distance(lookup, &name.as_str()); + let dist = lev_distance(lookup, name.as_str()); if dist <= max_dist { Some((name, dist)) } else { None } }) // Here we are collecting the next structure: @@ -88,7 +88,7 @@ fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option { iter_names.iter().fold(None, |result, candidate| { - if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) { + if sort_by_words(candidate.as_str()) == sort_by_words(lookup) { Some(*candidate) } else { result diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -20,7 +20,6 @@ #![feature(negative_impls)] #![feature(nll)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #[macro_use] extern crate rustc_macros; @@ -425,7 +424,7 @@ /// `SpanData` is public because `Span` uses a thread-local interner and can't be /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, @@ -435,6 +434,36 @@ pub parent: Option, } +// Order spans by position in the file. +impl Ord for SpanData { + fn cmp(&self, other: &Self) -> Ordering { + let SpanData { + lo: s_lo, + hi: s_hi, + ctxt: s_ctxt, + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. + parent: _, + } = self; + let SpanData { + lo: o_lo, + hi: o_hi, + ctxt: o_ctxt, + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. + parent: _, + } = other; + + (s_lo, s_hi, s_ctxt).cmp(&(o_lo, o_hi, o_ctxt)) + } +} + +impl PartialOrd for SpanData { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl SpanData { #[inline] pub fn span(&self) -> Span { @@ -551,6 +580,16 @@ matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) } + /// Gate suggestions that would not be appropriate in a context the user didn't write. + pub fn can_be_used_for_suggestions(self) -> bool { + !self.from_expansion() + // FIXME: If this span comes from a `derive` macro but it points at code the user wrote, + // the callsite span and the span will be pointing at different places. It also means that + // we can safely provide suggestions on this span. + || (matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) + && self.parent_callsite().map(|p| (p.lo(), p.hi())) != Some((self.lo(), self.hi()))) + } + #[inline] pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, SyntaxContext::root(), None) @@ -1374,7 +1413,7 @@ // Encode the first element. lines[0].encode(s)?; - let diff_iter = lines[..].array_windows().map(|&[fst, snd]| snd - fst); + let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst); match bytes_per_diff { 1 => { @@ -1497,7 +1536,7 @@ assert!(end_pos <= u32::MAX as usize); let (lines, multibyte_chars, non_narrow_chars) = - analyze_source_file::analyze_source_file(&src[..], start_pos); + analyze_source_file::analyze_source_file(&src, start_pos); SourceFile { name, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/symbol.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/symbol.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/symbol.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_span/src/symbol.rs 2022-02-23 04:07:21.000000000 +0000 @@ -196,6 +196,7 @@ Implied, Input, Into, + IntoFuture, IntoIterator, IoRead, IoWrite, @@ -331,6 +332,7 @@ asm_const, asm_experimental_arch, asm_sym, + asm_unwind, assert, assert_inhabited, assert_macro, @@ -437,6 +439,7 @@ compiler_builtins, compiler_fence, concat, + concat_bytes, concat_idents, conservative_impl_trait, console, @@ -497,6 +500,7 @@ core_panic_macro, cosf32, cosf64, + count, cr, crate_id, crate_in_paths, @@ -627,6 +631,7 @@ fdiv_fast, feature, fence, + ferris: "🦀", fetch_update, ffi, ffi_const, @@ -737,6 +742,7 @@ inout, instruction_set, intel, + into_future, into_iter, intra_doc_pointers, intrinsics, @@ -782,6 +788,7 @@ literal, llvm_asm, load, + loaded_from_disk, local, local_inner_macros, log10f32, @@ -815,6 +822,7 @@ maxnumf32, maxnumf64, may_dangle, + may_unwind, maybe_uninit, maybe_uninit_uninit, maybe_uninit_zeroed, @@ -1048,8 +1056,11 @@ reg64, reg_abcd, reg_byte, + reg_iw, reg_nonzero, - reg_thumb, + reg_pair, + reg_ptr, + reg_upper, register_attr, register_tool, relaxed_adts, @@ -1377,7 +1388,13 @@ unmarked_api, unpin, unreachable, + unreachable_2015, + unreachable_2015_macro, + unreachable_2021, + unreachable_2021_macro, unreachable_code, + unreachable_display, + unreachable_macro, unrestricted_attribute_tokens, unsafe_block_in_unsafe_fn, unsafe_cell, @@ -1502,9 +1519,12 @@ Ident::new(self.name, self.span.normalize_to_macro_rules()) } - /// Convert the name to a `SymbolStr`. This is a slowish operation because - /// it requires locking the symbol interner. - pub fn as_str(self) -> SymbolStr { + /// Access the underlying string. This is a slowish operation because it + /// requires locking the symbol interner. + /// + /// Note that the lifetime of the return value is a lie. See + /// `Symbol::as_str()` for details. + pub fn as_str(&self) -> &str { self.name.as_str() } } @@ -1640,12 +1660,17 @@ with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } - /// Convert to a `SymbolStr`. This is a slowish operation because it + /// Access the underlying string. This is a slowish operation because it /// requires locking the symbol interner. - pub fn as_str(self) -> SymbolStr { - with_session_globals(|session_globals| { - let symbol_str = session_globals.symbol_interner.get(self); - unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } } + /// + /// Note that the lifetime of the return value is a lie. It's not the same + /// as `&self`, but actually tied to the lifetime of the underlying + /// interner. Interners are long-lived, and there are very few of them, and + /// this function is typically used for short-lived things, so in practice + /// it works out ok. + pub fn as_str(&self) -> &str { + with_session_globals(|session_globals| unsafe { + std::mem::transmute::<&str, &str>(session_globals.symbol_interner.get(*self)) }) } @@ -1668,19 +1693,19 @@ impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.as_str(), f) + fmt::Debug::fmt(self.as_str(), f) } } impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) + fmt::Display::fmt(self.as_str(), f) } } impl Encodable for Symbol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) + s.emit_str(self.as_str()) } } @@ -1699,11 +1724,10 @@ } impl ToStableHashKey for Symbol { - type KeyType = SymbolStr; - + type KeyType = String; #[inline] - fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr { - self.as_str() + fn to_stable_hash_key(&self, _: &CTX) -> String { + self.as_str().to_string() } } @@ -1716,8 +1740,9 @@ // found that to regress performance up to 2% in some cases. This might be // revisited after further improvements to `indexmap`. // -// This type is private to prevent accidentally constructing more than one `Interner` on the same -// thread, which makes it easy to mixup `Symbol`s between `Interner`s. +// This type is private to prevent accidentally constructing more than one +// `Interner` on the same thread, which makes it easy to mixup `Symbol`s +// between `Interner`s. #[derive(Default)] struct InternerInner { arena: DroplessArena, @@ -1743,14 +1768,20 @@ let name = Symbol::new(inner.strings.len() as u32); - // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be - // UTF-8. + // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena, + // and immediately convert the clone back to `&[u8], all because there + // is no `inner.arena.alloc_str()` method. This is clearly safe. let string: &str = unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) }; - // It is safe to extend the arena allocation to `'static` because we only access - // these while the arena is still alive. + + // SAFETY: we can extend the arena allocation to `'static` because we + // only access these while the arena is still alive. let string: &'static str = unsafe { &*(string as *const str) }; inner.strings.push(string); + + // This second hash table lookup can be avoided by using `RawEntryMut`, + // but this code path isn't hot enough for it to be worth it. See + // #91445 for details. inner.names.insert(string, name); name } @@ -1888,70 +1919,3 @@ self.name.can_be_raw() && self.is_reserved() } } - -/// An alternative to [`Symbol`], useful when the chars within the symbol need to -/// be accessed. It deliberately has limited functionality and should only be -/// used for temporary values. -/// -/// Because the interner outlives any thread which uses this type, we can -/// safely treat `string` which points to interner data, as an immortal string, -/// as long as this type never crosses between threads. -// -// FIXME: ensure that the interner outlives any thread which uses `SymbolStr`, -// by creating a new thread right after constructing the interner. -#[derive(Clone, Eq, PartialOrd, Ord)] -pub struct SymbolStr { - string: &'static str, -} - -// This impl allows a `SymbolStr` to be directly equated with a `String` or -// `&str`. -impl> std::cmp::PartialEq for SymbolStr { - fn eq(&self, other: &T) -> bool { - self.string == other.deref() - } -} - -impl !Send for SymbolStr {} -impl !Sync for SymbolStr {} - -/// This impl means that if `ss` is a `SymbolStr`: -/// - `*ss` is a `str`; -/// - `&*ss` is a `&str` (and `match &*ss { ... }` is a common pattern). -/// - `&ss as &str` is a `&str`, which means that `&ss` can be passed to a -/// function expecting a `&str`. -impl std::ops::Deref for SymbolStr { - type Target = str; - #[inline] - fn deref(&self) -> &str { - self.string - } -} - -impl fmt::Debug for SymbolStr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.string, f) - } -} - -impl fmt::Display for SymbolStr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.string, f) - } -} - -impl HashStable for SymbolStr { - #[inline] - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.string.hash_stable(hcx, hasher) - } -} - -impl ToStableHashKey for SymbolStr { - type KeyType = SymbolStr; - - #[inline] - fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr { - self.clone() - } -} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/legacy.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/legacy.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/legacy.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/legacy.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,7 +13,7 @@ use std::fmt::{self, Write}; use std::mem::{self, discriminant}; -pub(super) fn mangle( +pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: Option, @@ -199,7 +199,7 @@ // `PrettyPrinter` aka pretty printing of e.g. types in paths, // symbol names should have their own printing machinery. -impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { +impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { type Error = fmt::Error; type Path = Self; @@ -255,7 +255,7 @@ } fn path_crate(self, cnum: CrateNum) -> Result { - self.write_str(&self.tcx.crate_name(cnum).as_str())?; + self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(self) } fn path_qualified( @@ -311,8 +311,8 @@ ) -> Result { self = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(self); } @@ -345,7 +345,7 @@ } } -impl PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -90,8 +90,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(never_type)] #![feature(nll)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![recursion_limit = "256"] #[macro_use] @@ -117,7 +115,7 @@ /// This function computes the symbol name for the given `instance` and the /// given instantiating crate. That is, if you know that instance X is /// instantiated in crate Y, this is the symbol name this instance would have. -pub fn symbol_name_for_instance_in_crate( +pub fn symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: CrateNum, @@ -132,7 +130,7 @@ // The `symbol_name` query provides the symbol name for calling a given // instance from the local crate. In particular, it will also look up the // correct symbol name of instances from upstream crates. -fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName<'tcx> { +fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName<'tcx> { let symbol_name = compute_symbol_name(tcx, instance, || { // This closure determines the instantiating crate for instances that // need an instantiating-crate-suffix for their symbol name, in order @@ -152,14 +150,14 @@ } /// This function computes the typeid for the given function ABI. -pub fn typeid_for_fnabi(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { +pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { v0::mangle_typeid_for_fnabi(tcx, fn_abi) } /// Computes the symbol name for the given instance. This function will call /// `compute_instantiating_crate` if it needs to factor the instantiating crate /// into the symbol name. -fn compute_symbol_name( +fn compute_symbol_name<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, compute_instantiating_crate: impl FnOnce() -> CrateNum, @@ -239,7 +237,7 @@ // Pick the crate responsible for the symbol mangling version, which has to: // 1. be stable for each instance, whether it's being defined or imported - // 2. obey each crate's own `-Z symbol-mangling-version`, as much as possible + // 2. obey each crate's own `-C symbol-mangling-version`, as much as possible // We solve these as follows: // 1. because symbol names depend on both `def_id` and `instantiating_crate`, // both their `CrateNum`s are stable for any given instance, so we can pick @@ -247,7 +245,7 @@ // 2. we favor `instantiating_crate` where possible (i.e. when `Some`) let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate); let mangling_version = if mangling_version_crate == LOCAL_CRATE { - tcx.sess.opts.debugging_opts.get_symbol_mangling_version() + tcx.sess.opts.get_symbol_mangling_version() } else { tcx.symbol_mangling_version(mangling_version_crate) }; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/test.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/test.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/test.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/test.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ tcx: TyCtxt<'tcx>, } -impl SymbolNamesTest<'tcx> { +impl SymbolNamesTest<'_> { fn process_attrs(&mut self, def_id: LocalDefId) { let tcx = self.tcx; for attr in tcx.get_attrs(def_id.to_def_id()).iter() { @@ -59,7 +59,7 @@ } } -impl hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> { +impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.process_attrs(item.def_id); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/v0.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/v0.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/v0.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_symbol_mangling/src/v0.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,6 +9,7 @@ use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_span::symbol::kw; use rustc_target::abi::call::FnAbi; use rustc_target::abi::Integer; use rustc_target::spec::abi::Abi; @@ -17,7 +18,7 @@ use std::iter; use std::ops::Range; -pub(super) fn mangle( +pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: Option, @@ -56,7 +57,7 @@ std::mem::take(&mut cx.out) } -pub(super) fn mangle_typeid_for_fnabi( +pub(super) fn mangle_typeid_for_fnabi<'tcx>( _tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> String { @@ -118,7 +119,7 @@ consts: FxHashMap<&'tcx ty::Const<'tcx>, usize>, } -impl SymbolMangler<'tcx> { +impl<'tcx> SymbolMangler<'tcx> { fn push(&mut self, s: &str) { self.out.push_str(s); } @@ -250,7 +251,7 @@ } } -impl Printer<'tcx> for &mut SymbolMangler<'tcx> { +impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { type Error = !; type Path = Self; @@ -559,7 +560,7 @@ ty::ExistentialPredicate::Projection(projection) => { let name = cx.tcx.associated_item(projection.item_def_id).ident; cx.push("p"); - cx.push_ident(&name.as_str()); + cx.push_ident(name.as_str()); cx = projection.ty.print(cx)?; } ty::ExistentialPredicate::AutoTrait(def_id) => { @@ -702,12 +703,11 @@ // just to be able to handle disambiguators. let disambiguated_field = self.tcx.def_key(field_def.did).disambiguated_data; - let field_name = - disambiguated_field.data.get_opt_name().map(|s| s.as_str()); + let field_name = disambiguated_field.data.get_opt_name(); self.push_disambiguator( disambiguated_field.disambiguator as u64, ); - self.push_ident(&field_name.as_ref().map_or("", |s| &s[..])); + self.push_ident(field_name.unwrap_or(kw::Empty).as_str()); self = field.print(self)?; } @@ -736,8 +736,8 @@ self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.to_u64()); - let name = self.tcx.crate_name(cnum).as_str(); - self.push_ident(&name); + let name = self.tcx.crate_name(cnum); + self.push_ident(name.as_str()); Ok(self) } @@ -771,6 +771,10 @@ disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let ns = match disambiguated_data.data { + // FIXME: It shouldn't be necessary to add anything for extern block segments, + // but we add 't' for backward compatibility. + DefPathData::ForeignMod => 't', + // Uppercase categories are more stable than lowercase ones. DefPathData::TypeNs(_) => 't', DefPathData::ValueNs(_) => 'v', @@ -789,13 +793,13 @@ } }; - let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str()); + let name = disambiguated_data.data.get_opt_name(); self.path_append_ns( print_prefix, ns, disambiguated_data.disambiguator as u64, - name.as_ref().map_or("", |s| &s[..]), + name.unwrap_or(kw::Empty).as_str(), ) } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mips64.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mips64.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mips64.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mips64.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,6 @@ -use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Reg, Uniform, +}; use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -115,7 +117,7 @@ for _ in 0..((offset - last_offset).bits() / 64) .min((prefix.len() - prefix_index) as u64) { - prefix[prefix_index] = Some(RegKind::Integer); + prefix[prefix_index] = Some(Reg::i64()); prefix_index += 1; } @@ -123,7 +125,7 @@ break; } - prefix[prefix_index] = Some(RegKind::Float); + prefix[prefix_index] = Some(Reg::f64()); prefix_index += 1; last_offset = offset + Reg::f64().size; } @@ -137,8 +139,13 @@ let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { prefix, - prefix_chunk_size: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, }); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -214,9 +214,9 @@ #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { - pub prefix: [Option; 8], - pub prefix_chunk_size: Size, + pub prefix: [Option; 8], pub rest: Uniform, + pub attrs: ArgAttributes, } impl From for CastTarget { @@ -227,29 +227,48 @@ impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform } + CastTarget { + prefix: [None; 8], + rest: uniform, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + } } } impl CastTarget { pub fn pair(a: Reg, b: Reg) -> CastTarget { CastTarget { - prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk_size: a.size, + prefix: [Some(a), None, None, None, None, None, None, None], rest: Uniform::from(b), + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, } } - pub fn size(&self, cx: &C) -> Size { - (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64) - .align_to(self.rest.align(cx)) - + self.rest.total + pub fn size(&self, _cx: &C) -> Size { + let mut size = self.rest.total; + for i in 0..self.prefix.iter().count() { + match self.prefix[i] { + Some(v) => size += Size { raw: v.size.bytes() }, + None => {} + } + } + return size; } pub fn align(&self, cx: &C) -> Align { self.prefix .iter() - .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx))) + .filter_map(|x| x.map(|reg| reg.align(cx))) .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| { acc.max(align) }) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/sparc64.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/sparc64.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/sparc64.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/abi/call/sparc64.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,9 @@ // FIXME: This needs an audit for correctness and completeness. -use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform, +}; +use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option where @@ -16,7 +18,7 @@ let valid_unit = match unit.kind { RegKind::Integer => false, - RegKind::Float => true, + RegKind::Float => false, RegKind::Vector => arg.layout.size.bits() == 128, }; @@ -24,33 +26,7 @@ }) } -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, -{ - if !ret.layout.is_aggregate() { - ret.extend_integer_width_to(64); - return; - } - - if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { - ret.cast_to(uniform); - return; - } - let size = ret.layout.size; - let bits = size.bits(); - if bits <= 256 { - let unit = Reg::i64(); - ret.cast_to(Uniform { unit, total: size }); - return; - } - - // don't return aggregates in registers - ret.make_indirect(); -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, @@ -60,13 +36,97 @@ return; } + // This doesn't intentionally handle structures with floats which needs + // special care below. if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { arg.cast_to(uniform); return; } + if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields { + let dl = cx.data_layout(); + let size = arg.layout.size; + let mut prefix = [None; 8]; + let mut prefix_index = 0; + let mut last_offset = Size::ZERO; + let mut has_float = false; + let mut arg_attribute = ArgAttribute::default(); + + for i in 0..arg.layout.fields.count() { + let field = arg.layout.field(cx, i); + let offset = arg.layout.fields.offset(i); + + if let abi::Abi::Scalar(scalar) = &field.abi { + if scalar.value == abi::F32 || scalar.value == abi::F64 { + has_float = true; + + if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + for _ in 0..((offset - last_offset).bits() / 64) + .min((prefix.len() - prefix_index) as u64) + { + prefix[prefix_index] = Some(Reg::i64()); + prefix_index += 1; + last_offset = last_offset + Reg::i64().size; + } + + if last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + if prefix_index == prefix.len() { + break; + } + + if scalar.value == abi::F32 { + arg_attribute = ArgAttribute::InReg; + prefix[prefix_index] = Some(Reg::f32()); + last_offset = offset + Reg::f32().size; + } else { + prefix[prefix_index] = Some(Reg::f64()); + last_offset = offset + Reg::f64().size; + } + prefix_index += 1; + } + } + } + + if has_float && arg.layout.size <= in_registers_max { + let mut rest_size = size - last_offset; + + if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() { + prefix[prefix_index] = Some(Reg::i32()); + rest_size = rest_size - Reg::i32().size; + } + + arg.cast_to(CastTarget { + prefix, + rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: arg_attribute, + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + }); + return; + } + } + let total = arg.layout.size; - if total.bits() > 128 { + if total > in_registers_max { arg.make_indirect(); return; } @@ -80,13 +140,13 @@ C: HasDataLayout, { if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); + classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 }); } for arg in &mut fn_abi.args { if arg.is_ignore() { continue; } - classify_arg(cx, arg); + classify_arg(cx, arg, Size { raw: 16 }); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/aarch64.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/aarch64.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/aarch64.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/aarch64.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,4 +1,5 @@ use super::{InlineAsmArch, InlineAsmType}; +use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -70,6 +71,22 @@ } } +pub fn reserved_x18( + _arch: InlineAsmArch, + _has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + if target.os == "android" + || target.is_like_fuchsia + || target.is_like_osx + || target.is_like_windows + { + Err("x18 is a reserved register on this target") + } else { + Ok(()) + } +} + def_regs! { AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass { x0: reg = ["x0", "w0"], @@ -90,6 +107,7 @@ x15: reg = ["x15", "w15"], x16: reg = ["x16", "w16"], x17: reg = ["x17", "w17"], + x18: reg = ["x18", "w18"] % reserved_x18, x20: reg = ["x20", "w20"], x21: reg = ["x21", "w21"], x22: reg = ["x22", "w22"], @@ -149,8 +167,6 @@ p14: preg = ["p14"], p15: preg = ["p15"], ffr: preg = ["ffr"], - #error = ["x18", "w18"] => - "x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm", #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/arm.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/arm.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/arm.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/arm.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,6 @@ def_reg_class! { Arm ArmInlineAsmRegClass { reg, - reg_thumb, sreg, sreg_low16, dreg, @@ -47,7 +46,7 @@ _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)] { match self { - Self::reg | Self::reg_thumb => types! { _: I8, I16, I32, F32; }, + Self::reg => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; }, Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { "vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); @@ -88,20 +87,49 @@ } } +fn not_thumb1( + _arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + _target: &Target, +) -> Result<(), &'static str> { + if has_feature("thumb-mode") && !has_feature("thumb2") { + Err("high registers (r8+) cannot be used in Thumb-1 code") + } else { + Ok(()) + } +} + +fn reserved_r9( + arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + not_thumb1(arch, &mut has_feature, target)?; + + // We detect this using the reserved-r9 feature instead of using the target + // because the relocation model can be changed with compiler options. + if has_feature("reserved-r9") { + Err("the RWPI static base register (r9) cannot be used as an operand for inline asm") + } else { + Ok(()) + } +} + def_regs! { Arm ArmInlineAsmReg ArmInlineAsmRegClass { - r0: reg, reg_thumb = ["r0", "a1"], - r1: reg, reg_thumb = ["r1", "a2"], - r2: reg, reg_thumb = ["r2", "a3"], - r3: reg, reg_thumb = ["r3", "a4"], - r4: reg, reg_thumb = ["r4", "v1"], - r5: reg, reg_thumb = ["r5", "v2"], - r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7, - r8: reg = ["r8", "v5"], - r10: reg = ["r10", "sl"], + r0: reg = ["r0", "a1"], + r1: reg = ["r1", "a2"], + r2: reg = ["r2", "a3"], + r3: reg = ["r3", "a4"], + r4: reg = ["r4", "v1"], + r5: reg = ["r5", "v2"], + r7: reg = ["r7", "v4"] % frame_pointer_r7, + r8: reg = ["r8", "v5"] % not_thumb1, + r9: reg = ["r9", "v6", "rfp"] % reserved_r9, + r10: reg = ["r10", "sl"] % not_thumb1, r11: reg = ["r11", "fp"] % frame_pointer_r11, - r12: reg = ["r12", "ip"], - r14: reg = ["r14", "lr"], + r12: reg = ["r12", "ip"] % not_thumb1, + r14: reg = ["r14", "lr"] % not_thumb1, s0: sreg, sreg_low16 = ["s0"], s1: sreg, sreg_low16 = ["s1"], s2: sreg, sreg_low16 = ["s2"], @@ -184,8 +212,6 @@ q15: qreg = ["q15"], #error = ["r6", "v3"] => "r6 is used internally by LLVM and cannot be used as an operand for inline asm", - #error = ["r9", "v6", "rfp"] => - "r9 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r13", "sp"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r15", "pc"] => diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/avr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/avr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/avr.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/avr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,196 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + Avr AvrInlineAsmRegClass { + reg, + reg_upper, + reg_pair, + reg_iw, + reg_ptr, + } +} + +impl AvrInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] { + match self { + Self::reg_pair | Self::reg_iw | Self::reg_ptr => &['h', 'l'], + _ => &[], + } + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg => types! { _: I8; }, + Self::reg_upper => types! { _: I8; }, + Self::reg_pair => types! { _: I16; }, + Self::reg_iw => types! { _: I16; }, + Self::reg_ptr => types! { _: I16; }, + } + } +} + +def_regs! { + Avr AvrInlineAsmReg AvrInlineAsmRegClass { + r2: reg = ["r2"], + r3: reg = ["r3"], + r4: reg = ["r4"], + r5: reg = ["r5"], + r6: reg = ["r6"], + r7: reg = ["r7"], + r8: reg = ["r8"], + r9: reg = ["r9"], + r10: reg = ["r10"], + r11: reg = ["r11"], + r12: reg = ["r12"], + r13: reg = ["r13"], + r14: reg = ["r14"], + r15: reg = ["r15"], + r16: reg, reg_upper = ["r16"], + r17: reg, reg_upper = ["r17"], + r18: reg, reg_upper = ["r18"], + r19: reg, reg_upper = ["r19"], + r20: reg, reg_upper = ["r20"], + r21: reg, reg_upper = ["r21"], + r22: reg, reg_upper = ["r22"], + r23: reg, reg_upper = ["r23"], + r24: reg, reg_upper = ["r24"], + r25: reg, reg_upper = ["r25"], + r26: reg, reg_upper = ["r26", "XL"], + r27: reg, reg_upper = ["r27", "XH"], + r30: reg, reg_upper = ["r30", "ZL"], + r31: reg, reg_upper = ["r31", "ZH"], + + r3r2: reg_pair = ["r3r2"], + r5r4: reg_pair = ["r5r4"], + r7r6: reg_pair = ["r7r6"], + r9r8: reg_pair = ["r9r8"], + r11r10: reg_pair = ["r11r10"], + r13r12: reg_pair = ["r13r12"], + r15r14: reg_pair = ["r15r14"], + r17r16: reg_pair = ["r17r16"], + r19r18: reg_pair = ["r19r18"], + r21r20: reg_pair = ["r21r20"], + r23r22: reg_pair = ["r23r22"], + + r25r24: reg_iw, reg_pair = ["r25r24"], + + X: reg_ptr, reg_iw, reg_pair = ["r27r26", "X"], + Z: reg_ptr, reg_iw, reg_pair = ["r31r30", "Z"], + + #error = ["Y", "YL", "YH"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["SP", "SPL", "SPH"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["r0", "r1", "r1r0"] => + "r0 and r1 are not available due to an issue in LLVM", + } +} + +macro_rules! emit_pairs { + ( + $self:ident $modifier:ident, + $($pair:ident $name:literal $hi:literal $lo:literal,)* + ) => { + match ($self, $modifier) { + $( + (AvrInlineAsmReg::$pair, Some('h')) => $hi, + (AvrInlineAsmReg::$pair, Some('l')) => $lo, + (AvrInlineAsmReg::$pair, _) => $name, + )* + _ => $self.name(), + } + }; +} + +impl AvrInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + modifier: Option, + ) -> fmt::Result { + let name = emit_pairs! { + self modifier, + Z "Z" "ZH" "ZL", + X "X" "XH" "XL", + r25r24 "r25:r24" "r25" "r24", + r23r22 "r23:r22" "r23" "r22", + r21r20 "r21:r20" "r21" "r20", + r19r18 "r19:r18" "r19" "r18", + r17r16 "r17:r16" "r17" "r16", + r15r14 "r15:r14" "r15" "r14", + r13r12 "r13:r12" "r13" "r12", + r11r10 "r11:r10" "r11" "r10", + r9r8 "r9:r8" "r9" "r8", + r7r6 "r7:r6" "r7" "r6", + r5r4 "r5:r4" "r5" "r4", + r3r2 "r3:r2" "r3" "r2", + }; + out.write_str(name) + } + + pub fn overlapping_regs(self, mut cb: impl FnMut(AvrInlineAsmReg)) { + cb(self); + + macro_rules! reg_conflicts { + ( + $( + $pair:ident : $hi:ident $lo:ident, + )* + ) => { + match self { + $( + Self::$pair => { + cb(Self::$hi); + cb(Self::$lo); + } + Self::$hi => { + cb(Self::$pair); + } + Self::$lo => { + cb(Self::$pair); + } + )* + } + }; + } + + reg_conflicts! { + Z : r31 r30, + X : r27 r26, + r25r24 : r25 r24, + r23r22 : r23 r22, + r21r20 : r21 r20, + r19r18 : r19 r18, + r17r16 : r17 r16, + r15r14 : r15 r14, + r13r12 : r13 r12, + r11r10 : r11 r10, + r9r8 : r9 r8, + r7r6 : r7 r6, + r5r4 : r5 r4, + r3r2 : r3 r2, + } + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/asm/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -148,6 +148,7 @@ mod aarch64; mod arm; +mod avr; mod bpf; mod hexagon; mod mips; @@ -161,6 +162,7 @@ pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; +pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; @@ -191,6 +193,7 @@ Wasm32, Wasm64, Bpf, + Avr, } impl FromStr for InlineAsmArch { @@ -215,6 +218,7 @@ "wasm32" => Ok(Self::Wasm32), "wasm64" => Ok(Self::Wasm64), "bpf" => Ok(Self::Bpf), + "avr" => Ok(Self::Avr), _ => Err(()), } } @@ -245,6 +249,7 @@ SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), + Avr(AvrInlineAsmReg), // Placeholder for invalid register constraints for the current target Err, } @@ -261,6 +266,7 @@ Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), Self::Err => "", } } @@ -276,6 +282,7 @@ Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), + Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } } @@ -291,40 +298,43 @@ let name = name.as_str(); Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { - Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Arm => { - Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::AArch64 => { - Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { - Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Nvptx64 => { - Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { - Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Hexagon => { - Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::S390x => { - Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::SpirV => { - Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { - Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Bpf => { - Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, name)?) + } + InlineAsmArch::Avr => { + Self::Avr(AvrInlineAsmReg::parse(arch, has_feature, target, name)?) } }) } @@ -347,6 +357,7 @@ Self::Mips(r) => r.emit(out, arch, modifier), Self::S390x(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), + Self::Avr(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -362,6 +373,7 @@ Self::Mips(_) => cb(self), Self::S390x(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), + Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -392,6 +404,7 @@ SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), + Avr(AvrInlineAsmRegClass), // Placeholder for invalid register constraints for the current target Err, } @@ -411,6 +424,7 @@ Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), Self::Err => rustc_span::symbol::sym::reg, } } @@ -432,6 +446,7 @@ Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), + Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -460,6 +475,7 @@ Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Bpf(r) => r.suggest_modifier(arch, ty), + Self::Avr(r) => r.suggest_modifier(arch, ty), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -484,6 +500,7 @@ Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch), Self::Bpf(r) => r.default_modifier(arch), + Self::Avr(r) => r.default_modifier(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -507,6 +524,7 @@ Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), Self::Bpf(r) => r.supported_types(arch), + Self::Avr(r) => r.supported_types(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -535,6 +553,7 @@ Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?) } InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(arch, name)?), }) } @@ -554,6 +573,7 @@ Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch), Self::Bpf(r) => r.valid_modifiers(arch), + Self::Avr(r) => r.valid_modifiers(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -739,6 +759,11 @@ bpf::fill_reg_map(arch, has_feature, target, &mut map); map } + InlineAsmArch::Avr => { + let mut map = avr::regclass_map(); + avr::fill_reg_map(arch, has_feature, target, &mut map); + map + } } } @@ -760,6 +785,7 @@ X86_64SysV, Arm, AArch64, + AArch64NoX18, RiscV, } @@ -768,10 +794,11 @@ /// clobber ABIs for the target. pub fn parse( arch: InlineAsmArch, + has_feature: impl FnMut(&str) -> bool, target: &Target, name: Symbol, ) -> Result { - let name = &*name.as_str(); + let name = name.as_str(); match arch { InlineAsmArch::X86 => match name { "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => { @@ -791,7 +818,13 @@ _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64), + "C" | "system" | "efiapi" => { + Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { @@ -866,8 +899,25 @@ AArch64 AArch64InlineAsmReg { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, - // x18 is platform-reserved or temporary, but we exclude it - // here since it is a reserved register. + x16, x17, x18, x30, + + // Technically the low 64 bits of v8-v15 are preserved, but + // we have no way of expressing this using clobbers. + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + p0, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11, p12, p13, p14, p15, + ffr, + + } + }, + InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { + AArch64 AArch64InlineAsmReg { + x0, x1, x2, x3, x4, x5, x6, x7, + x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x30, // Technically the low 64 bits of v8-v15 are preserved, but @@ -885,7 +935,8 @@ }, InlineAsmClobberAbi::Arm => clobbered_regs! { Arm ArmInlineAsmReg { - // r9 is platform-reserved and is treated as callee-saved. + // r9 is either platform-reserved or callee-saved. Either + // way we don't need to clobber it. r0, r1, r2, r3, r12, r14, // The finest-grained register variant is used here so that diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,6 +16,7 @@ #![feature(min_specialization)] #![feature(step_trait)] +use std::iter::FromIterator; use std::path::{Path, PathBuf}; #[macro_use] @@ -47,12 +48,11 @@ /// `"lib*/rustlib/x86_64-unknown-linux-gnu"`. pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf { let libdir = find_libdir(sysroot); - std::array::IntoIter::new([ + PathBuf::from_iter([ Path::new(libdir.as_ref()), Path::new(RUST_LIB_DIR), Path::new(target_triple), ]) - .collect::() } /// The name of the directory rustc expects libraries to be located. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,6 @@ pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; base.features = "+neon,+fp-armv8".to_string(); Target { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,6 @@ pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "aarch64-pc-windows-msvc".to_string(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/android_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/android_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/android_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/android_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ .push("-Wl,--allow-multiple-definition".to_string()); base.dwarf_version = Some(2); base.position_independent_executables = true; - base.has_elf_tls = false; + base.has_thread_local = false; // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867 // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution // was to always emit `uwtable`). diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,7 +16,7 @@ // 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_elf_tls = macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = macos_deployment_target("x86_64") >= (10, 7); TargetOptions { os: os.to_string(), @@ -33,7 +33,7 @@ has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), - has_elf_tls, + has_thread_local, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_sdk_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_sdk_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_sdk_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/apple_sdk_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -53,7 +53,7 @@ dynamic_linking: false, executables: true, link_env_remove: link_env_remove(arch), - has_elf_tls: false, + has_thread_local: false, ..super::apple_base::opts(os) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/fuchsia_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/fuchsia_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/fuchsia_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/fuchsia_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -35,7 +35,7 @@ (LinkOutputKind::StaticPicExe, &["Scrt1.o"]), ]), position_independent_executables: true, - has_elf_tls: true, + has_thread_local: true, ..Default::default() } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/hermit_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/hermit_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/hermit_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/hermit_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), executables: true, - has_elf_tls: true, + has_thread_local: true, pre_link_args, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,6 @@ let mut base = super::windows_uwp_msvc_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "i686-pc-windows-msvc".to_string(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/illumos_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/illumos_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/illumos_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/illumos_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -45,7 +45,7 @@ // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently // missing in illumos. For now at least, we must fallback to using // pthread_{get,set}specific. - //has_elf_tls: true, + //has_thread_local: true, // FIXME: Currently, rust is invoking cc to link, which ends up // causing these to get included twice. We should eventually transition diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/linux_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/linux_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/linux_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/linux_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,7 @@ has_rpath: true, position_independent_executables: true, relro_level: RelroLevel::Full, - has_elf_tls: true, + has_thread_local: true, crt_static_respected: true, ..Default::default() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -42,6 +42,7 @@ use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeMap; use std::convert::TryFrom; +use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -478,7 +479,7 @@ /// /// * Windows - not supported /// * macOS - supported, scattered object files - /// * ELF - supported, scattered `*.dwo` files + /// * ELF - supported, scattered `*.dwo` or `*.o` files (see `SplitDwarfKind`) Unpacked, } @@ -866,6 +867,7 @@ ("powerpc-unknown-freebsd", powerpc_unknown_freebsd), ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd), ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd), + ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd), ("x86_64-unknown-freebsd", x86_64_unknown_freebsd), ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly), @@ -1277,9 +1279,8 @@ /// `argc` and `argv` values. pub main_needs_argc_argv: bool, - /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for - /// this target. - pub has_elf_tls: bool, + /// Flag indicating whether #[thread_local] is available for this target. + pub has_thread_local: bool, // This is mainly for easy compatibility with emscripten. // If we give emcc .o files that are actually .bc files it // will 'just work'. @@ -1485,7 +1486,7 @@ archive_format: "gnu".to_string(), main_needs_argc_argv: true, allow_asm: true, - has_elf_tls: false, + has_thread_local: false, obj_is_bitcode: false, forces_embed_bitcode: false, bitcode_llvm_cmdline: String::new(), @@ -2072,7 +2073,7 @@ key!(archive_format); key!(allow_asm, bool); key!(main_needs_argc_argv, bool); - key!(has_elf_tls, bool); + key!(has_thread_local, bool); key!(obj_is_bitcode, bool); key!(forces_embed_bitcode, bool); key!(bitcode_llvm_cmdline); @@ -2173,12 +2174,11 @@ // Additionally look in the sysroot under `lib/rustlib//target.json` // as a fallback. let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple); - let p = std::array::IntoIter::new([ + let p = PathBuf::from_iter([ Path::new(sysroot), Path::new(&rustlib_path), Path::new("target.json"), - ]) - .collect::(); + ]); if p.is_file() { return load_file(&p); } @@ -2314,7 +2314,7 @@ target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(main_needs_argc_argv); - target_option_val!(has_elf_tls); + target_option_val!(has_thread_local); target_option_val!(obj_is_bitcode); target_option_val!(forces_embed_bitcode); target_option_val!(bitcode_llvm_cmdline); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/redox_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/redox_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/redox_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/redox_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,7 @@ has_rpath: true, position_independent_executables: true, relro_level: RelroLevel::Full, - has_elf_tls: true, + has_thread_local: true, crt_static_default: true, crt_static_respected: true, ..Default::default() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs 2022-02-23 04:07:21.000000000 +0000 @@ -0,0 +1,18 @@ +use crate::spec::{CodeModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-freebsd".to_string(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(), + arch: "riscv64".to_string(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".to_string(), + features: "+m,+a,+f,+d,+c".to_string(), + llvm_abiname: "lp64d".to_string(), + max_atomic_width: Some(64), + ..super::freebsd_base::opts() + }, + } +} diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/solid_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/solid_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/solid_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/solid_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ os: format!("solid_{}", kernel), vendor: "kmc".to_string(), frame_pointer: FramePointer::NonLeaf, - has_elf_tls: true, + has_thread_local: true, ..Default::default() } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,6 @@ options: TargetOptions { features: "+vfp3,+neon".to_string(), max_atomic_width: Some(64), - has_elf_tls: true, // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is // implemented for windows/arm in LLVM panic_strategy: PanicStrategy::Abort, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/vxworks_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/vxworks_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/vxworks_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/vxworks_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ executables: true, families: vec!["unix".to_string()], has_rpath: true, - has_elf_tls: true, + has_thread_local: true, crt_static_default: true, crt_static_respected: true, crt_static_allows_dylibs: true, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/wasm_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/wasm_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/wasm_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/wasm_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -120,9 +120,9 @@ // When the atomics feature is activated then these two keys matter, // otherwise they're basically ignored by the standard library. In this // mode, however, the `#[thread_local]` attribute works (i.e. - // `has_elf_tls`) and we need to get it to work by specifying + // `has_thread_local`) and we need to get it to work by specifying // `local-exec` as that's all that's implemented in LLVM today for wasm. - has_elf_tls: true, + has_thread_local: true, tls_model: TlsModel::LocalExec, // gdb scripts don't work on wasm blobs diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/windows_msvc_base.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/windows_msvc_base.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/windows_msvc_base.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/windows_msvc_base.rs 2022-02-23 04:07:21.000000000 +0000 @@ -27,6 +27,7 @@ // linking some libraries which require a specific agreement, so it may // not ever be possible for us to pass this flag. no_default_libraries: false, + has_thread_local: true, ..base } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,6 @@ let mut base = super::windows_msvc_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,7 +8,7 @@ base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; - base.has_elf_tls = false; + base.has_thread_local = false; // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI // breaks code gen. See LLVM bug 36743 base.needs_plt = true; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,6 @@ let mut base = super::windows_uwp_msvc_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/Cargo.toml rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/Cargo.toml --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/Cargo.toml 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/Cargo.toml 2022-02-23 04:07:21.000000000 +0000 @@ -12,9 +12,9 @@ rustc_index = { path = "../rustc_index" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.55.0" -chalk-solve = "0.55.0" -chalk-engine = "0.55.0" +chalk-ir = "0.75.0" +chalk-engine = "0.75.0" +chalk-solve = "0.75.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/db.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/db.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/db.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/db.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,7 +46,9 @@ .iter() .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars)) .map(|wc| wc.fold_with(&mut regions_substitutor)) - .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect() + .filter_map(|wc| LowerInto::< + Option>> + >::lower_into(wc, self.interner)).collect() } fn bounds_for(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec @@ -58,14 +60,14 @@ .explicit_item_bounds(def_id) .iter() .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| LowerInto::>::lower_into(bound, &self.interner)) + .filter_map(|bound| LowerInto::>::lower_into(bound, self.interner)) .collect() } } impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'tcx> { - fn interner(&self) -> &RustInterner<'tcx> { - &self.interner + fn interner(&self) -> RustInterner<'tcx> { + self.interner } fn associated_ty_data( @@ -83,7 +85,7 @@ _ => unimplemented!("Not possible??"), } let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); let bounds = self.bounds_for(def_id, bound_vars); @@ -107,7 +109,7 @@ let trait_def = self.interner.tcx.trait_def(def_id); let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); @@ -170,7 +172,7 @@ let adt_def = adt_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, adt_def.did); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(adt_def.did, bound_vars); @@ -181,7 +183,7 @@ fields: variant .fields .iter() - .map(|field| field.ty(self.interner.tcx, bound_vars).lower_into(&self.interner)) + .map(|field| field.ty(self.interner.tcx, bound_vars).lower_into(self.interner)) .collect(), }) .collect(); @@ -209,8 +211,8 @@ adt_id: chalk_ir::AdtId>, ) -> Arc>> { let adt_def = adt_id.0; - let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)).intern(&self.interner); - let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)).intern(&self.interner); + let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)).intern(self.interner); + let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)).intern(self.interner); Arc::new(chalk_solve::rust_ir::AdtRepr { c: adt_def.repr.c(), packed: adt_def.repr.packed(), @@ -241,25 +243,25 @@ ) -> Arc>> { let def_id = fn_def_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); let sig = self.interner.tcx.fn_sig(def_id); let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars( - &self.interner, + self.interner, self.interner.tcx, sig.inputs_and_output().subst(self.interner.tcx, bound_vars), ); let argument_types = inputs_and_output[..inputs_and_output.len() - 1] .iter() - .map(|t| t.subst(self.interner.tcx, &bound_vars).lower_into(&self.interner)) + .map(|t| t.subst(self.interner.tcx, &bound_vars).lower_into(self.interner)) .collect(); let return_type = inputs_and_output[inputs_and_output.len() - 1] .subst(self.interner.tcx, &bound_vars) - .lower_into(&self.interner); + .lower_into(self.interner); let bound = chalk_solve::rust_ir::FnDefDatumBound { inputs_and_output: chalk_ir::Binders::new( @@ -270,7 +272,7 @@ }; Arc::new(chalk_solve::rust_ir::FnDefDatum { id: fn_def_id, - sig: sig.lower_into(&self.interner), + sig: sig.lower_into(self.interner), binders: chalk_ir::Binders::new(binders, bound), }) } @@ -281,7 +283,7 @@ ) -> Arc>> { let def_id = impl_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let trait_ref = self.interner.tcx.impl_trait_ref(def_id).expect("not an impl"); let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars); @@ -292,7 +294,7 @@ let where_clauses = self.where_clauses_for(def_id, bound_vars); let value = chalk_solve::rust_ir::ImplDatumBound { - trait_ref: trait_ref.lower_into(&self.interner), + trait_ref: trait_ref.lower_into(self.interner), where_clauses, }; @@ -306,7 +308,7 @@ .collect(); Arc::new(chalk_solve::rust_ir::ImplDatum { - polarity: self.interner.tcx.impl_polarity(def_id).lower_into(&self.interner), + polarity: self.interner.tcx.impl_polarity(def_id).lower_into(self.interner), binders: chalk_ir::Binders::new(binders, value), impl_type: chalk_solve::rust_ir::ImplType::Local, associated_ty_value_ids, @@ -336,10 +338,10 @@ let mut regions_substitutor = lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); let self_ty = self_ty.fold_with(&mut regions_substitutor); - let lowered_ty = self_ty.lower_into(&self.interner); + let lowered_ty = self_ty.lower_into(self.interner); - parameters[0].assert_ty_ref(&self.interner).could_match( - &self.interner, + parameters[0].assert_ty_ref(self.interner).could_match( + self.interner, self.unification_database(), &lowered_ty, ) @@ -452,13 +454,13 @@ .find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id) .unwrap(); let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let ty = self .interner .tcx .type_of(def_id) .subst(self.interner.tcx, bound_vars) - .lower_into(&self.interner); + .lower_into(self.interner); Arc::new(chalk_solve::rust_ir::AssociatedTyValue { impl_id: chalk_ir::ImplId(impl_id), @@ -521,13 +523,13 @@ .filter_map(|bound| { LowerInto::< Option>> - >::lower_into(bound, &self.interner) + >::lower_into(bound, self.interner) }) .collect(); // Binder for the bound variable representing the concrete impl Trait type. let existential_binder = chalk_ir::VariableKinds::from1( - &self.interner, + self.interner, chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), ); @@ -536,7 +538,7 @@ where_clauses: chalk_ir::Binders::new(existential_binder, where_clauses), }; - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, bound: chalk_ir::Binders::new(binders, value), @@ -568,6 +570,7 @@ Unpin => lang_items.unpin_trait(), CoerceUnsized => lang_items.coerce_unsized_trait(), DiscriminantKind => lang_items.discriminant_kind_trait(), + Generator => lang_items.generator_return(), }; def_id.map(chalk_ir::TraitId) } @@ -584,7 +587,7 @@ self.interner .tcx .mk_ty(ty::Tuple(self.interner.tcx.intern_substs(&[]))) - .lower_into(&self.interner) + .lower_into(self.interner) } fn closure_kind( @@ -592,8 +595,8 @@ _closure_id: chalk_ir::ClosureId>, substs: &chalk_ir::Substitution>, ) -> chalk_solve::rust_ir::ClosureKind { - let kind = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 3]; - match kind.assert_ty_ref(&self.interner).kind(&self.interner) { + let kind = &substs.as_slice(self.interner)[substs.len(self.interner) - 3]; + match kind.assert_ty_ref(self.interner).kind(self.interner) { chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(int_ty)) => match int_ty { chalk_ir::IntTy::I8 => chalk_solve::rust_ir::ClosureKind::Fn, chalk_ir::IntTy::I16 => chalk_solve::rust_ir::ClosureKind::FnMut, @@ -610,18 +613,17 @@ substs: &chalk_ir::Substitution>, ) -> chalk_ir::Binders>> { - let sig = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 2]; - match sig.assert_ty_ref(&self.interner).kind(&self.interner) { + let sig = &substs.as_slice(self.interner)[substs.len(self.interner) - 2]; + match sig.assert_ty_ref(self.interner).kind(self.interner) { chalk_ir::TyKind::Function(f) => { - let substitution = f.substitution.0.as_slice(&self.interner); - let return_type = - substitution.last().unwrap().assert_ty_ref(&self.interner).clone(); + let substitution = f.substitution.0.as_slice(self.interner); + let return_type = substitution.last().unwrap().assert_ty_ref(self.interner).clone(); // Closure arguments are tupled - let argument_tuple = substitution[0].assert_ty_ref(&self.interner); - let argument_types = match argument_tuple.kind(&self.interner) { + let argument_tuple = substitution[0].assert_ty_ref(self.interner); + let argument_types = match argument_tuple.kind(self.interner) { chalk_ir::TyKind::Tuple(_len, substitution) => substitution - .iter(&self.interner) - .map(|arg| arg.assert_ty_ref(&self.interner)) + .iter(self.interner) + .map(|arg| arg.assert_ty_ref(self.interner)) .cloned() .collect(), _ => bug!("Expecting closure FnSig args to be tupled."), @@ -629,7 +631,7 @@ chalk_ir::Binders::new( chalk_ir::VariableKinds::from_iter( - &self.interner, + self.interner, (0..f.num_binders).map(|_| chalk_ir::VariableKind::Lifetime), ), chalk_solve::rust_ir::FnDefInputsAndOutputDatum { argument_types, return_type }, @@ -645,7 +647,7 @@ substs: &chalk_ir::Substitution>, ) -> chalk_ir::Binders>> { let inputs_and_output = self.closure_inputs_and_output(_closure_id, substs); - let tuple = substs.as_slice(&self.interner).last().unwrap().assert_ty_ref(&self.interner); + let tuple = substs.as_slice(self.interner).last().unwrap().assert_ty_ref(self.interner); inputs_and_output.map_ref(|_| tuple.clone()) } @@ -654,8 +656,8 @@ _closure_id: chalk_ir::ClosureId>, substs: &chalk_ir::Substitution>, ) -> chalk_ir::Substitution> { - let substitution = &substs.as_slice(&self.interner)[0..substs.len(&self.interner) - 3]; - chalk_ir::Substitution::from_iter(&self.interner, substitution) + let substitution = &substs.as_slice(self.interner)[0..substs.len(self.interner) - 3]; + chalk_ir::Substitution::from_iter(self.interner, substitution) } fn generator_datum( @@ -691,7 +693,7 @@ ) -> chalk_ir::Variances> { let variances = self.interner.tcx.variances_of(def_id.0); chalk_ir::Variances::from_iter( - &self.interner, + self.interner, variances.iter().map(|v| match v { ty::Variance::Invariant => chalk_ir::Variance::Invariant, ty::Variance::Covariant => chalk_ir::Variance::Covariant, @@ -707,7 +709,7 @@ ) -> chalk_ir::Variances> { let variances = self.interner.tcx.variances_of(def_id.0.did); chalk_ir::Variances::from_iter( - &self.interner, + self.interner, variances.iter().map(|v| match v { ty::Variance::Invariant => chalk_ir::Variance::Invariant, ty::Variance::Covariant => chalk_ir::Variance::Covariant, @@ -722,7 +724,7 @@ /// var bound at index `0`. For types, we use a `BoundVar` index equal to /// the type parameter index. For regions, we use the `BoundRegionKind::BrNamed` /// variant (which has a `DefId`). -fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { +fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { InternalSubsts::for_item(tcx, def_id, |param, substs| match param.kind { ty::GenericParamDefKind::Type { .. } => tcx .mk_ty(ty::Bound( @@ -752,7 +754,7 @@ } fn binders_for<'tcx>( - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, bound_vars: SubstsRef<'tcx>, ) -> chalk_ir::VariableKinds> { chalk_ir::VariableKinds::from_iter( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/lowering.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/lowering.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/lowering.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/lowering.rs 2022-02-23 04:07:21.000000000 +0000 @@ -46,26 +46,26 @@ /// Essentially an `Into` with a `&RustInterner` parameter crate trait LowerInto<'tcx, T> { /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk type, consuming `self`. - fn lower_into(self, interner: &RustInterner<'tcx>) -> T; + fn lower_into(self, interner: RustInterner<'tcx>) -> T; } impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution>> for SubstsRef<'tcx> { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_ir::Substitution> { chalk_ir::Substitution::from_iter(interner, self.iter().map(|s| s.lower_into(interner))) } } impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> SubstsRef<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> { interner.tcx.mk_substs(self.iter(interner).map(|subst| subst.lower_into(interner))) } } impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy>> for ty::ProjectionTy<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasTy> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy> { chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id), substitution: self.substs.lower_into(interner), @@ -78,7 +78,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_ir::InEnvironment>> { let clauses = self.environment.into_iter().map(|predicate| { let (predicate, binders, _named_regions) = @@ -122,18 +122,18 @@ chalk_ir::ProgramClauseData(chalk_ir::Binders::new(binders, value)).intern(interner) }); - let goal: chalk_ir::GoalData> = self.goal.lower_into(&interner); + let goal: chalk_ir::GoalData> = self.goal.lower_into(interner); chalk_ir::InEnvironment { environment: chalk_ir::Environment { - clauses: chalk_ir::ProgramClauses::from_iter(&interner, clauses), + clauses: chalk_ir::ProgramClauses::from_iter(interner, clauses), }, - goal: goal.intern(&interner), + goal: goal.intern(interner), } } } impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predicate<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -214,7 +214,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef>> for rustc_middle::ty::TraitRef<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::TraitRef> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::TraitRef> { chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(self.def_id), substitution: self.substs.lower_into(interner), @@ -225,7 +225,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> for rustc_middle::ty::ProjectionPredicate<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasEq> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { chalk_ir::AliasEq { ty: self.ty.lower_into(interner), alias: self.projection_ty.lower_into(interner), @@ -234,7 +234,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Ty> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty> { let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)); let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)); let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f)); @@ -336,7 +336,7 @@ } impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> Ty<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> { use chalk_ir::TyKind; let kind = match self.kind(interner) { @@ -429,7 +429,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Lifetime> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Lifetime> { use rustc_middle::ty::RegionKind::*; match self { @@ -459,7 +459,7 @@ } impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> Region<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> { let kind = match self.data(interner) { chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound( ty::DebruijnIndex::from_u32(var.debruijn.depth()), @@ -487,7 +487,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::Const>> for ty::Const<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Const> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Const> { let ty = self.ty.lower_into(interner); let value = match self.val { ty::ConstKind::Value(val) => { @@ -503,7 +503,7 @@ } impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> ty::Const<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> ty::Const<'tcx> { let data = self.data(interner); let ty = data.ty.lower_into(interner); let val = match data.value { @@ -520,7 +520,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg>> for GenericArg<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GenericArg> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GenericArg> { match self.unpack() { ty::subst::GenericArgKind::Type(ty) => { chalk_ir::GenericArgData::Ty(ty.lower_into(interner)) @@ -539,7 +539,7 @@ impl<'tcx> LowerInto<'tcx, ty::subst::GenericArg<'tcx>> for &chalk_ir::GenericArg> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> ty::subst::GenericArg<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> ty::subst::GenericArg<'tcx> { match self.data(interner) { chalk_ir::GenericArgData::Ty(ty) => { let t: Ty<'tcx> = ty.lower_into(interner); @@ -566,7 +566,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> Option>> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -610,7 +610,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_ir::Binders>> { // `Self` has one binder: // Binder<&'tcx ty::List>> @@ -680,7 +680,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder<'tcx, ty::FnSig<'tcx>> { - fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig> { + fn lower_into(self, _interner: RustInterner<'_>) -> FnSig> { chalk_ir::FnSig { abi: self.abi(), safety: match self.unsafety() { @@ -700,7 +700,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> Option>> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -737,7 +737,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_solve::rust_ir::TraitBound> { chalk_solve::rust_ir::TraitBound { trait_id: chalk_ir::TraitId(self.def_id), @@ -747,7 +747,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::Mutability> for ast::Mutability { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_ir::Mutability { + fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_ir::Mutability { match self { rustc_ast::Mutability::Mut => chalk_ir::Mutability::Mut, rustc_ast::Mutability::Not => chalk_ir::Mutability::Not, @@ -756,7 +756,7 @@ } impl<'tcx> LowerInto<'tcx, ast::Mutability> for chalk_ir::Mutability { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> ast::Mutability { + fn lower_into(self, _interner: RustInterner<'tcx>) -> ast::Mutability { match self { chalk_ir::Mutability::Mut => ast::Mutability::Mut, chalk_ir::Mutability::Not => ast::Mutability::Not, @@ -765,7 +765,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity { + fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity { match self { ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive, ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative, @@ -780,7 +780,7 @@ { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_solve::rust_ir::AliasEqBound> { let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx); chalk_solve::rust_ir::AliasEqBound { @@ -802,7 +802,7 @@ /// late-bound regions, even outside of fn contexts, since this is the best way /// to prep types for chalk lowering. crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, tcx: TyCtxt<'tcx>, ty: Binder<'tcx, T>, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/chalk/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -63,7 +63,7 @@ > = chalk_ir::UCanonical { canonical: chalk_ir::Canonical { binders: chalk_ir::CanonicalVarKinds::from_iter( - &interner, + interner, obligation.variables.iter().map(|v| match v.kind { CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(), CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(), @@ -89,7 +89,7 @@ CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(), }), ), - value: obligation.value.lower_into(&interner), + value: obligation.value.lower_into(interner), }, universes: max_universe + 1, }; @@ -110,11 +110,11 @@ use rustc_middle::infer::canonical::CanonicalVarInfo; let mut var_values: IndexVec> = IndexVec::new(); - subst.as_slice(&interner).iter().for_each(|p| { - var_values.push(p.lower_into(&interner)); + subst.as_slice(interner).iter().for_each(|p| { + var_values.push(p.lower_into(interner)); }); let variables: Vec<_> = binders - .iter(&interner) + .iter(interner) .map(|var| { let kind = match var.kind { chalk_ir::VariableKind::Ty(ty_kind) => CanonicalVarKind::Ty(match ty_kind { @@ -134,8 +134,7 @@ CanonicalVarInfo { kind } }) .collect(); - let max_universe = - binders.iter(&interner).map(|v| v.skip_kind().counter).max().unwrap_or(0); + let max_universe = binders.iter(interner).map(|v| v.skip_kind().counter).max().unwrap_or(0); let sol = Canonical { max_universe: ty::UniverseIndex::from_usize(max_universe), variables: tcx.intern_canonical_var_infos(&variables), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/implied_outlives_bounds.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/implied_outlives_bounds.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/implied_outlives_bounds.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/implied_outlives_bounds.rs 2022-02-23 04:07:21.000000000 +0000 @@ -138,7 +138,7 @@ /// this down to determine what relationships would have to hold for /// `T: 'a` to hold. We get to assume that the caller has validated /// those relationships. -fn implied_bounds_from_components( +fn implied_bounds_from_components<'tcx>( sub_region: ty::Region<'tcx>, sup_components: SmallVec<[Component<'tcx>; 4]>, ) -> Vec> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,6 @@ //! the guts are broken up into modules; see the comments in those modules. #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(nll)] #![recursion_limit = "256"] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,27 +8,28 @@ crate fn provide(p: &mut Providers) { *p = Providers { - normalize_generic_arg_after_erasing_regions: |tcx, goal| { - debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); + try_normalize_generic_arg_after_erasing_regions: |tcx, goal| { + debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal); tcx.sess .perf_stats .normalize_generic_arg_after_erasing_regions .fetch_add(1, Ordering::Relaxed); - normalize_after_erasing_regions(tcx, goal) + + try_normalize_after_erasing_regions(tcx, goal) }, - normalize_mir_const_after_erasing_regions: |tcx, goal| { - normalize_after_erasing_regions(tcx, goal) + try_normalize_mir_const_after_erasing_regions: |tcx, goal| { + try_normalize_after_erasing_regions(tcx, goal) }, ..*p }; } #[instrument(level = "debug", skip(tcx))] -fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( +fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, goal: ParamEnvAnd<'tcx, T>, -) -> T { +) -> Result { let ParamEnvAnd { param_env, value } = goal; tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); @@ -49,14 +50,14 @@ debug_assert_eq!(normalized_value, resolved_value); let erased = infcx.tcx.erase_regions(resolved_value); debug_assert!(!erased.needs_infer(), "{:?}", erased); - erased + Ok(erased) } - Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), + Err(NoSolution) => Err(NoSolution), } }) } -fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool { +fn not_outlives_predicate<'tcx>(p: &ty::Predicate<'tcx>) -> bool { match p.kind().skip_binder() { ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false, ty::PredicateKind::Trait(..) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/type_op.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/type_op.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/type_op.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_traits/src/type_op.rs 2022-02-23 04:07:21.000000000 +0000 @@ -70,7 +70,7 @@ fulfill_cx: &'me mut dyn TraitEngine<'tcx>, } -impl AscribeUserTypeCx<'me, 'tcx> { +impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { fn normalize(&mut self, value: T) -> T where T: TypeFoldable<'tcx>, @@ -195,7 +195,7 @@ }) } -fn type_op_normalize( +fn type_op_normalize<'tcx, T>( infcx: &InferCtxt<'_, 'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, Normalize>, @@ -210,28 +210,28 @@ Ok(value) } -fn type_op_normalize_ty( +fn type_op_normalize_ty<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_predicate( +fn type_op_normalize_predicate<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_fn_sig( +fn type_op_normalize_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_poly_fn_sig( +fn type_op_normalize_poly_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/autoderef.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/autoderef.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/autoderef.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/autoderef.rs 2022-02-23 04:07:21.000000000 +0000 @@ -3,7 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; use rustc_session::{DiagnosticMessageId, Limit}; use rustc_span::def_id::LOCAL_CRATE; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/infer.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/infer.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/infer.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/infer.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,6 @@ use rustc_middle::traits::query::Fallible; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_span::{Span, DUMMY_SP}; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,8 +16,7 @@ #![feature(drain_filter)] #![feature(derive_default_enum)] #![feature(hash_drain_filter)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] +#![feature(label_break_value)] #![feature(let_else)] #![feature(never_type)] #![feature(crate_visibility_modifier)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/opaque_types.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/opaque_types.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/opaque_types.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/opaque_types.rs 2022-02-23 04:07:21.000000000 +0000 @@ -97,7 +97,7 @@ span: Span, } -impl ReverseMapper<'tcx> { +impl<'tcx> ReverseMapper<'tcx> { fn new( tcx: TyCtxt<'tcx>, tainted_by_errors: bool, @@ -134,7 +134,7 @@ } } -impl TypeFolder<'tcx> for ReverseMapper<'tcx> { +impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -338,7 +338,7 @@ /// Requires that trait definitions have been processed so that we can /// elaborate predicates and walk supertraits. #[instrument(skip(tcx, predicates), level = "debug")] -crate fn required_region_bounds( +crate fn required_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, predicates: impl Iterator>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs 2022-02-23 04:07:21.000000000 +0000 @@ -219,7 +219,7 @@ } } -impl AutoTraitFinder<'tcx> { +impl<'tcx> AutoTraitFinder<'tcx> { /// The core logic responsible for computing the bounds for our synthesized impl. /// /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like @@ -370,12 +370,17 @@ computed_preds.clone().chain(user_computed_preds.iter().cloned()), ) .map(|o| o.predicate); - new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal()); + new_env = ty::ParamEnv::new( + tcx.mk_predicates(normalized_preds), + param_env.reveal(), + param_env.constness(), + ); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), user_env.reveal(), + user_env.constness(), ); debug!( "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \ @@ -834,7 +839,17 @@ _ => return false, } } - _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate), + // There's not really much we can do with these predicates - + // we start out with a `ParamEnv` with no inference variables, + // and these don't correspond to adding any new bounds to + // the `ParamEnv`. + ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} }; } true diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,7 +16,7 @@ relationships: FxHashMap, } -impl FulfillmentContext<'tcx> { +impl FulfillmentContext<'_> { crate fn new() -> Self { FulfillmentContext { obligations: FxIndexSet::default(), @@ -25,7 +25,7 @@ } } -impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { +impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn normalize_projection_type( &mut self, infcx: &InferCtxt<'_, 'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/codegen.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/codegen.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/codegen.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/codegen.rs 2022-02-23 04:07:21.000000000 +0000 @@ -107,7 +107,7 @@ /// type inference variables that appear in `result` to be /// unified, and hence we need to process those obligations to get /// the complete picture of the type. -fn drain_fulfillment_cx_or_panic( +fn drain_fulfillment_cx_or_panic<'tcx, T>( infcx: &InferCtxt<'_, 'tcx>, fulfill_cx: &mut FulfillmentContext<'tcx>, result: T, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/coherence.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/coherence.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/coherence.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/coherence.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,9 +12,10 @@ self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; use std::iter; @@ -82,12 +83,11 @@ impl2_ref.iter().flat_map(|tref| tref.substs.types()), ) .any(|(ty1, ty2)| { - let t1 = fast_reject::simplify_type(tcx, ty1, false); - let t2 = fast_reject::simplify_type(tcx, ty2, false); + let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No); + let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No); if let (Some(t1), Some(t2)) = (t1, t2) { // Simplified successfully - // Types cannot unify if they differ in their reference mutability or simplify to different types - t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() + t1 != t2 } else { // Types might unify false @@ -154,18 +154,24 @@ }) } -fn overlap_within_probe( +fn overlap_within_probe<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, skip_leak_check: SkipLeakCheck, a_def_id: DefId, b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Option> { - fn loose_check(selcx: &mut SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + fn loose_check<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + o: &PredicateObligation<'tcx>, + ) -> bool { !selcx.predicate_may_hold_fatal(o) } - fn strict_check(selcx: &SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + fn strict_check<'cx, 'tcx>( + selcx: &SelectionContext<'cx, 'tcx>, + o: &PredicateObligation<'tcx>, + ) -> bool { let infcx = selcx.infcx(); let tcx = infcx.tcx; o.flip_polarity(tcx) @@ -498,9 +504,7 @@ return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type)); } - for input_ty in non_local_tys { - non_local_spans.push((input_ty, i == 0)); - } + non_local_spans.extend(non_local_tys.into_iter().map(|input_ty| (input_ty, i == 0))); } // If we exit above loop, never found a local type. debug!("orphan_check_trait_ref: no local type"); @@ -520,7 +524,11 @@ /// - for `Foo`, where `Foo` is a local type, this returns `[]`. /// - `&mut u32` returns `[u32]`, as `&mut` is a fundamental type, similar to `Box`. /// - `Box>` returns `[]`, as `Box` is a fundamental type and `Foo` is local. -fn contained_non_local_types(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { +fn contained_non_local_types<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + in_crate: InCrate, +) -> Vec> { if ty_is_local_constructor(ty, in_crate) { Vec::new() } else { @@ -536,7 +544,7 @@ /// For `#[fundamental]` ADTs and `&T` / `&mut T`, returns `Some` with the /// type parameters of the ADT, or `T`, respectively. For non-fundamental /// types, returns `None`. -fn fundamental_ty_inner_tys( +fn fundamental_ty_inner_tys<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> Option>> { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs 2022-02-23 04:07:21.000000000 +0000 @@ -399,13 +399,25 @@ let arg = self.recurse_build(source)?; self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty)) } + ExprKind::Borrow{ arg, ..} => { + let arg_node = &self.body.exprs[*arg]; + // Skip reborrows for now until we allow Deref/Borrow/AddressOf + // expressions. + // FIXME(generic_const_exprs): Verify/explain why this is sound + if let ExprKind::Deref {arg} = arg_node.kind { + self.recurse_build(arg)? + } else { + self.maybe_supported_error( + node.span, + "borrowing is not supported in generic constants", + )? + } + } // FIXME(generic_const_exprs): We may want to support these. - ExprKind::AddressOf { .. } - | ExprKind::Borrow { .. } - | ExprKind::Deref { .. } => self.maybe_supported_error( + ExprKind::AddressOf { .. } | ExprKind::Deref {..}=> self.maybe_supported_error( node.span, - "dereferencing is not supported in generic constants", + "dereferencing or taking the address is not supported in generic constants", )?, ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error( node.span, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,10 +21,10 @@ use rustc_hir::Node; use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, - TypeFoldable, WithConstness, + self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; @@ -205,7 +205,7 @@ self.note_obligation_cause_code( &mut err, &obligation.predicate, - &obligation.cause.code, + obligation.cause.code(), &mut vec![], &mut Default::default(), ); @@ -255,7 +255,7 @@ // 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. if let ObligationCauseCode::WellFormed(Some(wf_loc)) = - root_obligation.cause.code.peel_derives() + root_obligation.cause.code().peel_derives() { if let Some(cause) = self .tcx @@ -272,7 +272,7 @@ | ObligationCauseCode::CompareImplTypeObligation { impl_item_def_id, trait_item_def_id, - } = obligation.cause.code + } = *obligation.cause.code() { self.report_extra_impl_obligation( span, @@ -295,7 +295,7 @@ } let trait_ref = trait_predicate.to_poly_trait_ref(); let (post_message, pre_message, type_def) = self - .get_parent_trait_ref(&obligation.cause.code) + .get_parent_trait_ref(obligation.cause.code()) .map(|(t, s)| { ( format!(" in `{}`", t), @@ -376,17 +376,18 @@ } } - let explanation = - if obligation.cause.code == ObligationCauseCode::MainFunctionType { - "consider using `()`, or a `Result`".to_owned() - } else { - format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref.print_only_trait_path(), - trait_ref.skip_binder().self_ty(), - ) - }; + let explanation = if let ObligationCauseCode::MainFunctionType = + obligation.cause.code() + { + "consider using `()`, or a `Result`".to_owned() + } else { + format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref.print_only_trait_path(), + trait_ref.skip_binder().self_ty(), + ) + }; if self.suggest_add_reference_to_arg( &obligation, @@ -439,6 +440,7 @@ self.suggest_remove_reference(&obligation, &mut err, trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); self.note_version_mismatch(&mut err, &trait_ref); + self.suggest_remove_await(&obligation, &mut err); if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { self.suggest_await_before_try(&mut err, &obligation, trait_ref, span); @@ -539,11 +541,6 @@ // is otherwise overwhelming and unhelpful (see #85844 for an // example). - let trait_is_debug = - self.tcx.is_diagnostic_item(sym::Debug, trait_ref.def_id()); - let trait_is_display = - self.tcx.is_diagnostic_item(sym::Display, trait_ref.def_id()); - let in_std_macro = match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { Some(macro_def_id) => { @@ -553,7 +550,12 @@ None => false, }; - if in_std_macro && (trait_is_debug || trait_is_display) { + if in_std_macro + && matches!( + self.tcx.get_diagnostic_name(trait_ref.def_id()), + Some(sym::Debug | sym::Display) + ) + { err.emit(); return; } @@ -1062,7 +1064,7 @@ } } -trait InferCtxtPrivExt<'tcx> { +trait InferCtxtPrivExt<'hir, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; @@ -1173,7 +1175,7 @@ ) -> bool; } -impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { +impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { @@ -1304,7 +1306,7 @@ ); let is_normalized_ty_expected = !matches!( - obligation.cause.code.peel_derives(), + obligation.cause.code().peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ObjectCastObligation(_) @@ -1338,7 +1340,46 @@ "type mismatch resolving `{}`", predicate ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); + let secondary_span = match predicate.kind().skip_binder() { + ty::PredicateKind::Projection(proj) => self + .tcx + .opt_associated_item(proj.projection_ty.item_def_id) + .and_then(|trait_assoc_item| { + self.tcx + .trait_of_item(proj.projection_ty.item_def_id) + .map(|id| (trait_assoc_item, id)) + }) + .and_then(|(trait_assoc_item, id)| { + self.tcx.find_map_relevant_impl( + id, + proj.projection_ty.self_ty(), + |did| { + self.tcx + .associated_items(did) + .in_definition_order() + .filter(|assoc| assoc.ident == trait_assoc_item.ident) + .next() + }, + ) + }) + .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(ty), + .. + }), + ) => { + Some((ty.span, format!("type mismatch resolving `{}`", predicate))) + } + _ => None, + }), + _ => None, + }; + self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true); self.note_obligation_cause(&mut diag, obligation); diag.emit(); } @@ -1400,14 +1441,32 @@ &self, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + // We simplify params and strip references here. + // + // This both removes a lot of unhelpful suggestions, e.g. + // when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`, + // while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`. + // + // The second thing isn't necessarily always a good thing, but + // any other simple setup results in a far worse output, so 🤷 + let simp = fast_reject::simplify_type( + self.tcx, + trait_ref.skip_binder().self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { Some(simp) => all_impls .filter_map(|def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = fast_reject::simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); if let Some(imp_simp) = imp_simp { if simp != imp_simp { return None; @@ -1508,14 +1567,14 @@ self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) }; let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); - let all_traits = self.tcx.all_traits(()); - let traits_with_same_path: std::collections::BTreeSet<_> = all_traits - .iter() - .filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) - .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path) + let traits_with_same_path: std::collections::BTreeSet<_> = self + .tcx + .all_traits() + .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) + .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) .collect(); for trait_with_same_path in traits_with_same_path { - if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) { + if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) { let impl_span = self.tcx.def_span(impl_def_id); err.span_help(impl_span, "trait impl with same name found"); let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); @@ -1562,9 +1621,7 @@ let predicate = self.resolve_vars_if_possible(obligation.predicate); let span = obligation.cause.span; - debug!( - ?predicate, ?obligation.cause.code, - ); + debug!(?predicate, obligation.cause.code = tracing::field::debug(&obligation.cause.code())); // Ambiguity errors are often caused as fallout from earlier errors. // We ignore them if this `infcx` is tainted in some cases below. @@ -1659,13 +1716,13 @@ } } - if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { + if let ObligationCauseCode::ItemObligation(def_id) = *obligation.cause.code() { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); } else if let ( Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _), ) = - (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) + (self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code()) { let generics = self.tcx.generics_of(*def_id); if generics.params.iter().any(|p| p.name != kw::SelfUpper) @@ -1948,7 +2005,7 @@ self.note_obligation_cause_code( err, &obligation.predicate, - &obligation.cause.code, + obligation.cause.code(), &mut vec![], &mut Default::default(), ); @@ -1961,15 +2018,16 @@ err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, ) { - let (pred, item_def_id, span) = - match (obligation.predicate.kind().skip_binder(), obligation.cause.code.peel_derives()) - { - ( - ty::PredicateKind::Trait(pred), - &ObligationCauseCode::BindingObligation(item_def_id, span), - ) => (pred, item_def_id, span), - _ => return, - }; + let (pred, item_def_id, span) = match ( + obligation.predicate.kind().skip_binder(), + obligation.cause.code().peel_derives(), + ) { + ( + ty::PredicateKind::Trait(pred), + &ObligationCauseCode::BindingObligation(item_def_id, span), + ) => (pred, item_def_id, span), + _ => return, + }; debug!( "suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}", pred, item_def_id, span @@ -1984,7 +2042,7 @@ self.maybe_suggest_unsized_generics(err, span, node); } - fn maybe_suggest_unsized_generics( + fn maybe_suggest_unsized_generics<'hir>( &self, err: &mut DiagnosticBuilder<'tcx>, span: Span, @@ -2025,9 +2083,7 @@ debug!("maybe_suggest_unsized_generics: param={:?}", param); match node { hir::Node::Item( - item - @ - hir::Item { + item @ hir::Item { // Only suggest indirection for uses of type parameters in ADTs. kind: hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..), @@ -2053,7 +2109,7 @@ ); } - fn maybe_indirection_for_unsized( + fn maybe_indirection_for_unsized<'hir>( &self, err: &mut DiagnosticBuilder<'tcx>, item: &'hir Item<'hir>, @@ -2097,10 +2153,21 @@ ) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); - - if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + let self_ty = parent_trait_ref.skip_binder().self_ty(); + if obligated_types.iter().any(|ot| ot == &self_ty) { return true; } + if let ty::Adt(def, substs) = self_ty.kind() { + if let [arg] = &substs[..] { + if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() { + if let ty::Adt(inner_def, _) = ty.kind() { + if inner_def == def { + return true; + } + } + } + } + } } false } @@ -2156,7 +2223,7 @@ } pub fn recursive_type_with_infinite_size_error( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, type_def_id: DefId, spans: Vec, ) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs 2022-02-23 04:07:21.000000000 +0000 @@ -129,7 +129,7 @@ self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()), )]; - match obligation.cause.code { + match obligation.cause.code() { ObligationCauseCode::BuiltinDerivedObligation(..) | ObligationCauseCode::ImplDerivedObligation(..) | ObligationCauseCode::DerivedObligation(..) => {} @@ -141,7 +141,7 @@ } if let ObligationCauseCode::ItemObligation(item) - | ObligationCauseCode::BindingObligation(item, _) = obligation.cause.code + | ObligationCauseCode::BindingObligation(item, _) = *obligation.cause.code() { // FIXME: maybe also have some way of handling methods // from other traits? That would require name resolution, @@ -231,7 +231,7 @@ if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) { - command.evaluate(self.tcx, trait_ref, &flags[..]) + command.evaluate(self.tcx, trait_ref, &flags) } else { OnUnimplementedNote::default() } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs 2022-02-23 04:07:21.000000000 +0000 @@ -9,7 +9,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lrc; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, }; @@ -21,7 +20,7 @@ use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, - Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, + Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; @@ -89,6 +88,12 @@ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ); + fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, @@ -192,7 +197,7 @@ /// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but /// it can also be an `impl Trait` param that needs to be decomposed to a type /// param for cleaner code. -fn suggest_restriction( +fn suggest_restriction<'tcx>( tcx: TyCtxt<'tcx>, generics: &hir::Generics<'tcx>, msg: &str, @@ -262,8 +267,8 @@ match generics .params .iter() - .map(|p| p.bounds_span().unwrap_or(p.span)) - .filter(|&span| generics.span.contains(span) && span.desugaring_kind().is_none()) + .map(|p| p.bounds_span_for_suggestions().unwrap_or(p.span.shrink_to_hi())) + .filter(|&span| generics.span.contains(span) && span.can_be_used_for_suggestions()) .max_by_key(|span| span.hi()) { // `fn foo(t: impl Trait)` @@ -271,7 +276,7 @@ None => (generics.span, format!("<{}>", type_param)), // `fn foo(t: impl Trait)` // ^^^ suggest `` here - Some(span) => (span.shrink_to_hi(), format!(", {}", type_param)), + Some(span) => (span, format!(", {}", type_param)), }, // `fn foo(t: impl Trait)` // ^ suggest `where ::A: Bound` @@ -491,7 +496,7 @@ ) { // It only make sense when suggesting dereferences for arguments let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - &obligation.cause.code + obligation.cause.code() { parent_code.clone() } else { @@ -656,7 +661,8 @@ } _ => return, }; - if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) { + if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) + { // When the obligation error has been ensured to have been caused by // an argument, the `obligation.cause.span` points at the expression // of the argument, so we can provide a suggestion. Otherwise, we give @@ -682,13 +688,13 @@ let span = obligation.cause.span; let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - &obligation.cause.code + obligation.cause.code() { - parent_code.clone() + &parent_code } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) = span.ctxt().outer_expn_data().kind { - Lrc::new(obligation.cause.code.clone()) + obligation.cause.code() } else { return false; }; @@ -741,7 +747,7 @@ let msg = format!( "the trait bound `{}: {}` is not satisfied", - orig_ty.to_string(), + orig_ty, old_ref.print_only_trait_path(), ); if has_custom_message { @@ -799,12 +805,12 @@ return false; }; - if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code { + if let ObligationCauseCode::ImplDerivedObligation(obligation) = code { try_borrowing(obligation.parent_trait_ref, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ItemObligation(_) = &*code + | ObligationCauseCode::ItemObligation(_) = code { - try_borrowing(*poly_trait_ref, &never_suggest_borrow[..]) + try_borrowing(*poly_trait_ref, &never_suggest_borrow) } else { false } @@ -873,6 +879,63 @@ } } + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let span = obligation.cause.span; + + if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() { + let hir = self.tcx.hir(); + if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) { + if let hir::Node::Expr(expr) = node { + // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` + // and if not maybe suggest doing something else? If we kept the expression around we + // could also check if it is an fn call (very likely) and suggest changing *that*, if + // it is from the local crate. + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(span.hi()), + "remove the `.await`", + String::new(), + Applicability::MachineApplicable, + ); + // FIXME: account for associated `async fn`s. + if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { + if let ty::PredicateKind::Trait(pred) = + obligation.predicate.kind().skip_binder() + { + err.span_label( + *span, + &format!("this call returns `{}`", pred.self_ty()), + ); + } + if let Some(typeck_results) = + self.in_progress_typeck_results.map(|t| t.borrow()) + { + let ty = typeck_results.expr_ty_adjusted(base); + if let ty::FnDef(def_id, _substs) = ty.kind() { + if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = + hir.get_if_local(*def_id) + { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "alternatively, consider making `fn {}` asynchronous", + ident + ), + "async ".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } + } + } + /// Check if the trait bound is implemented for a different mutability and note it in the /// final error. fn suggest_change_mut( @@ -882,7 +945,7 @@ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let points_at_arg = matches!( - obligation.cause.code, + obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }, ); @@ -1009,7 +1072,7 @@ obligation: &PredicateObligation<'tcx>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool { - match obligation.cause.code.peel_derives() { + match obligation.cause.code().peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. ObligationCauseCode::SizedReturnType => {} _ => return false, @@ -1132,7 +1195,7 @@ "; let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn"); - let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] }; + let trait_obj = if has_dyn { &snippet[4..] } else { &snippet }; if only_never_return { // No return paths, probably using `panic!()` or similar. // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box`. @@ -1204,7 +1267,7 @@ err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, ) { - match obligation.cause.code.peel_derives() { + match obligation.cause.code().peel_derives() { ObligationCauseCode::SizedReturnType => {} _ => return, } @@ -1398,7 +1461,7 @@ }; let mut generator = None; let mut outer_generator = None; - let mut next_code = Some(&obligation.cause.code); + let mut next_code = Some(obligation.cause.code()); let mut seen_upvar_tys_infer_tuple = false; @@ -1654,130 +1717,63 @@ format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = - |interior_span: Span, yield_span: Span, scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - // #70935: If snippet contains newlines, display "the value" instead - // so that we do not emit complex diagnostics. - let snippet = &format!("`{}`", snippet); - let snippet = if snippet.contains('\n') { "the value" } else { snippet }; - // The multispan can be complex here, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | baz(|| async{ - // | __________^___- - // | | _________| - // | || - // LL | || foo(tx.clone()); - // LL | || }).await; - // | || - ^- value is later dropped here - // | ||_________|______| - // | |__________| await occurs here, with value maybe used later - // | has type `closure` which is not `Send` - // - // So, detect it and separate into some notes, like: - // - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ first, await occurs here, with the value maybe used later... - // note: the value is later dropped here - // --> $DIR/issue-70935-complex-spans.rs:15:17 - // | - // LL | }).await; - // | ^ - // - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - let is_overlapped = - yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); - if is_overlapped { - span.push_span_label( - yield_span, - format!( - "first, {} occurs here, with {} maybe used later...", - await_or_yield, snippet - ), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - if source_map.is_multiline(interior_span) { - err.span_note( - scope_span, - &format!("{} is later dropped here", snippet), - ); - err.span_note( - interior_span, - &format!( - "this has type `{}` which {}", - target_ty, trait_explanation - ), - ); - } else { - let mut span = MultiSpan::from_span(scope_span); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note(span, &format!("{} is later dropped here", snippet)); - } - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - scope_span, - format!("{} is later dropped here", snippet), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - } + let mut explain_yield = |interior_span: Span, + yield_span: Span, + scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async { + // | ______________- + // | | + // | | + // LL | | foo(tx.clone()); + // LL | | }).await; + // | | - ^^^^^^ await occurs here, with value maybe used later + // | |__________| + // | has type `closure` which is not `Send` + // note: value is later dropped here + // LL | | }).await; + // | | ^ + // + span.push_span_label( + yield_span, + format!("{} occurs here, with {} maybe used later", await_or_yield, snippet), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + // If available, use the scope span to annotate the drop location. + let mut scope_note = None; + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + + let msg = format!("{} is later dropped here", snippet); + if source_map.is_multiline(yield_span.between(scope_span)) { + span.push_span_label(scope_span, msg); } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); + scope_note = Some((scope_span, msg)); } } - }; + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + if let Some((span, msg)) = scope_note { + err.span_note(span, &msg); + } + } + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { @@ -1935,6 +1931,9 @@ | ObligationCauseCode::ReturnType | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) + | ObligationCauseCode::AwaitableExpr(_) + | ObligationCauseCode::ForLoopIterator + | ObligationCauseCode::QuestionMark | ObligationCauseCode::LetElse => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); @@ -2185,6 +2184,16 @@ obligated_types, seen_requirements, ) + }); + } else { + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + err, + &parent_predicate, + &cause_code.peel_derives(), + obligated_types, + seen_requirements, + ) }); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs 2022-02-23 04:07:21.000000000 +0000 @@ -4,7 +4,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_hir as hir; +use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; @@ -21,12 +21,14 @@ use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; +use super::EvaluationResult; use super::Unimplemented; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; use crate::traits::error_reporting::InferCtxtExt as _; use crate::traits::project::PolyProjectionObligation; +use crate::traits::project::ProjectionCacheKeyExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { @@ -94,7 +96,7 @@ // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PendingPredicateObligation<'_>, 56); +static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. @@ -231,21 +233,6 @@ self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } - fn select_all_with_constness_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: rustc_hir::Constness, - ) -> Vec> { - { - let errors = self.select_with_constness_where_possible(infcx, constness); - if !errors.is_empty() { - return errors; - } - } - - self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() - } - fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -254,15 +241,6 @@ self.select(&mut selcx) } - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: hir::Constness, - ) -> Vec> { - let mut selcx = SelectionContext::with_constness(infcx, constness); - self.select(&mut selcx) - } - fn pending_obligations(&self) -> Vec> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } @@ -277,7 +255,7 @@ register_region_obligations: bool, } -fn mk_pending(os: Vec>) -> Vec> { +fn mk_pending(os: Vec>) -> Vec> { os.into_iter() .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) .collect() @@ -679,12 +657,7 @@ if obligation.predicate.is_known_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && infcx.predicate_must_hold_considering_regions(obligation) - { + if infcx.predicate_must_hold_considering_regions(obligation) { debug!( "selecting trait at depth {} evaluated to holds", obligation.recursion_depth @@ -738,12 +711,21 @@ if obligation.predicate.is_global(tcx) { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && self.selcx.infcx().predicate_must_hold_considering_regions(obligation) - { + if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) { + if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate( + &mut self.selcx, + project_obligation.predicate, + ) { + // If `predicate_must_hold_considering_regions` succeeds, then we've + // evaluated all sub-obligations. We can therefore mark the 'root' + // obligation as complete, and skip evaluating sub-obligations. + self.selcx + .infcx() + .inner + .borrow_mut() + .projection_cache() + .complete(key, EvaluationResult::EvaluatedToOk); + } return ProcessResult::Changed(vec![]); } else { tracing::debug!("Does NOT hold: {:?}", obligation); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/misc.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/misc.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/misc.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/misc.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,7 +16,7 @@ HasDestructor, } -pub fn can_type_implement_copy( +pub fn can_type_implement_copy<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, self_type: Ty<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -33,8 +33,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{ - self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness, - COMMON_VTABLE_ENTRIES, + self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, COMMON_VTABLE_ENTRIES, }; use rustc_span::{sym, Span}; use smallvec::SmallVec; @@ -307,8 +306,11 @@ debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - let elaborated_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()); + let elaborated_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); // HACK: we are trying to normalize the param-env inside *itself*. The problem is that // normalization expects its param-env to be already normalized, which means we have @@ -360,8 +362,11 @@ // predicates here anyway. Keeping them here anyway because it seems safer. let outlives_env: Vec<_> = non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); - let outlives_env = - ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal()); + let outlives_env = ty::ParamEnv::new( + tcx.intern_predicates(&outlives_env), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); let outlives_predicates = match do_normalize_predicates( tcx, region_context, @@ -381,7 +386,11 @@ let mut predicates = non_outlives_predicates; predicates.extend(outlives_predicates); debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ) } pub fn fully_normalize<'a, 'tcx, T>( @@ -564,14 +573,17 @@ .predicates .into_iter() .filter_map(move |(pred, _)| { - pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred() }); 'diving_in_skip_visited_traits: loop { if let Some(next_super_trait) = direct_super_traits_iter.next() { if visited.insert(next_super_trait.to_predicate(tcx)) { + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref); stack.push(( - next_super_trait.value, + next_super_trait, emit_vptr_on_new_entry, Some(direct_super_traits_iter), )); @@ -603,7 +615,11 @@ if let Some(siblings) = siblings_opt { if let Some(next_inner_most_trait_ref) = siblings.next() { if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) { - *inner_most_trait_ref = next_inner_most_trait_ref.value; + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_inner_most_trait_ref = + next_inner_most_trait_ref.map_bound(|t| t.trait_ref); + *inner_most_trait_ref = next_inner_most_trait_ref; *emit_vptr = emit_vptr_on_new_entry; break 'exiting_out; } else { @@ -785,7 +801,7 @@ } /// Find slot offset for trait vptr within vtable entries of another trait -pub fn vtable_trait_upcasting_coercion_new_vptr_slot( +pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( tcx: TyCtxt<'tcx>, key: ( Ty<'tcx>, // trait object type whose trait owning vtable diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,14 +18,13 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use smallvec::SmallVec; -use std::array; use std::iter; use std::ops::ControlFlow; @@ -51,10 +50,7 @@ violations } -fn object_safety_violations( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, -) -> &'tcx [ObjectSafetyViolation] { +fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [ObjectSafetyViolation] { debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("object_safety_violations: {:?}", trait_def_id); @@ -273,7 +269,7 @@ .collect() } -fn predicate_references_self( +fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, (predicate, sp): (ty::Predicate<'tcx>, Span), ) -> Option { @@ -692,13 +688,14 @@ .to_predicate(tcx) }; - let caller_bounds: Vec> = param_env - .caller_bounds() - .iter() - .chain(array::IntoIter::new([unsize_predicate, trait_predicate])) - .collect(); + let caller_bounds: Vec> = + param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect(); - ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&caller_bounds), + param_env.reveal(), + param_env.constness(), + ) }; // Receiver: DispatchFromDyn U]> diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs 2022-02-23 04:07:21.000000000 +0000 @@ -269,7 +269,7 @@ let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); let s = self.0.as_str(); - let parser = Parser::new(&s, None, None, false, ParseMode::Format); + let parser = Parser::new(s, None, None, false, ParseMode::Format); let mut result = Ok(()); for token in parser { match token { @@ -347,7 +347,7 @@ let empty_string = String::new(); let s = self.0.as_str(); - let parser = Parser::new(&s, None, None, false, ParseMode::Format); + 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 { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/project.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/project.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/project.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/project.rs 2022-02-23 04:07:21.000000000 +0000 @@ -10,7 +10,6 @@ use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::TraitQueryMode; use super::{ ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData, @@ -28,7 +27,7 @@ use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; @@ -570,7 +569,7 @@ } } -impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -678,7 +677,7 @@ } } -impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -889,7 +888,7 @@ debug!("recur cache"); return Err(InProgress); } - Err(ProjectionCacheEntry::NormalizedTy(ty)) => { + Err(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => { // This is the hottest path in this function. // // If we find the value in the cache, then return it along @@ -946,27 +945,11 @@ }; let mut deduped: SsoHashSet<_> = Default::default(); - let mut canonical = - SelectionContext::with_query_mode(selcx.infcx(), TraitQueryMode::Canonical); - result.obligations.drain_filter(|projected_obligation| { if !deduped.insert(projected_obligation.clone()) { return true; } - // If any global obligations always apply, considering regions, then we don't - // need to include them. The `is_global` check rules out inference variables, - // so there's no need for the caller of `opt_normalize_projection_type` - // to evaluate them. - // Note that we do *not* discard obligations that evaluate to - // `EvaluatedtoOkModuloRegions`. Evaluating these obligations - // inside of a query (e.g. `evaluate_obligation`) can change - // the result to `EvaluatedToOkModuloRegions`, while an - // `EvaluatedToOk` obligation will never change the result. - // See #85360 for more details - projected_obligation.is_global(canonical.tcx()) - && canonical - .evaluate_root_obligation(projected_obligation) - .map_or(false, |res| res.must_apply_considering_regions()) + false }); if use_cache { @@ -1937,14 +1920,14 @@ } } -crate trait ProjectionCacheKeyExt<'tcx>: Sized { +crate trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized { fn from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, ) -> Option; } -impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> { +impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { fn from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,3 +1,5 @@ +use rustc_middle::ty; + use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{ @@ -64,10 +66,21 @@ obligation: &PredicateObligation<'tcx>, ) -> Result { let mut _orig_values = OriginalQueryValues::default(); - let c_pred = self.canonicalize_query_keep_static( - obligation.param_env.and(obligation.predicate), - &mut _orig_values, - ); + + let param_env = match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => { + // we ignore the value set to it. + let mut _constness = pred.constness; + obligation + .param_env + .with_constness(_constness.and(obligation.param_env.constness())) + } + // constness has no effect on the given predicate. + _ => obligation.param_env.without_const(), + }; + + let c_pred = self + .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values); // Run canonical query. If overflow occurs, rerun from scratch but this time // in standard trait query mode so that overflow is handled appropriately // within `SelectionContext`. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; use rustc_middle::mir; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; @@ -61,7 +61,6 @@ cause: self.cause, param_env: self.param_env, obligations: vec![], - error: false, cache: SsoHashMap::new(), anon_depth: 0, universes: vec![], @@ -88,7 +87,7 @@ normalizer.universes.extend((0..max_visitor.escaping).map(|_| None)); } } - let result = value.fold_with(&mut normalizer); + let result = value.try_fold_with(&mut normalizer); info!( "normalize::<{}>: result={:?} with {} obligations", std::any::type_name::(), @@ -100,11 +99,7 @@ std::any::type_name::(), normalizer.obligations, ); - if normalizer.error { - Err(NoSolution) - } else { - Ok(Normalized { value: result, obligations: normalizer.obligations }) - } + result.map(|value| Normalized { value, obligations: normalizer.obligations }) } } @@ -171,34 +166,37 @@ param_env: ty::ParamEnv<'tcx>, obligations: Vec>, cache: SsoHashMap, Ty<'tcx>>, - error: bool, anon_depth: usize, universes: Vec>, } impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { + type Error = NoSolution; + fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { self.infcx.tcx } +} - fn fold_binder>( +impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { + fn try_fold_binder>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result, Self::Error> { self.universes.push(None); - let t = t.super_fold_with(self); + let t = t.try_super_fold_with(self); self.universes.pop(); t } #[instrument(level = "debug", skip(self))] - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { if !needs_normalization(&ty, self.param_env.reveal()) { - return ty; + return Ok(ty); } if let Some(ty) = self.cache.get(&ty) { - return ty; + return Ok(ty); } // See note in `rustc_trait_selection::traits::project` about why we @@ -212,10 +210,10 @@ ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty.super_fold_with(self), + Reveal::UserFacing => ty.try_super_fold_with(self), Reveal::All => { - let substs = substs.super_fold_with(self); + let substs = substs.try_super_fold_with(self)?; let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( @@ -240,7 +238,7 @@ ty ); } - let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty)); + let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); self.anon_depth -= 1; folded_ty } @@ -252,7 +250,7 @@ // we don't need to replace them with placeholders (see branch below). let tcx = self.infcx.tcx; - let data = data.super_fold_with(self); + let data = data.try_super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -262,39 +260,22 @@ .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - result.normalized_ty - } - - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(result.normalized_ty) } ty::Projection(data) => { @@ -308,7 +289,7 @@ &mut self.universes, data, ); - let data = data.super_fold_with(self); + let data = data.try_super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -318,57 +299,49 @@ .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - crate::traits::project::PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result.normalized_ty, - ) - } - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + )) } - _ => ty.super_fold_with(self), - })(); + _ => ty.try_super_fold_with(self), + })()?; self.cache.insert(ty, res); - res + Ok(res) } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let constant = constant.super_fold_with(self); - constant.eval(self.infcx.tcx, self.param_env) + fn try_fold_const( + &mut self, + constant: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + let constant = constant.try_super_fold_with(self)?; + Ok(constant.eval(self.infcx.tcx, self.param_env)) } - fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { - constant.super_fold_with(self) + fn try_fold_mir_const( + &mut self, + constant: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + constant.try_super_fold_with(self) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs 2022-02-23 04:07:21.000000000 +0000 @@ -31,7 +31,7 @@ ) -> Fallible>; } -impl Normalizable<'tcx> for Ty<'tcx> { +impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -40,7 +40,7 @@ } } -impl Normalizable<'tcx> for ty::Predicate<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -49,7 +49,7 @@ } } -impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -58,7 +58,7 @@ } } -impl Normalizable<'tcx> for ty::FnSig<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs 2022-02-23 04:07:21.000000000 +0000 @@ -14,7 +14,7 @@ } } -impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { +impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { type QueryResponse = DropckOutlivesResult<'tcx>; fn try_fast_path( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs 2022-02-23 04:07:21.000000000 +0000 @@ -30,8 +30,14 @@ fn perform_query( tcx: TyCtxt<'tcx>, - canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, + mut canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, ) -> Fallible> { + match canonicalized.value.value.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => { + canonicalized.value.param_env.remap_constness_with(pred.constness); + } + _ => canonicalized.value.param_env = canonicalized.value.param_env.without_const(), + } tcx.type_op_prove_predicate(canonicalized) } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs 2022-02-23 04:07:21.000000000 +0000 @@ -11,7 +11,7 @@ use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_target::spec::abi::Abi; use crate::traits; @@ -303,7 +303,7 @@ } else if lang_items.drop_trait() == Some(def_id) && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst { - if self.is_in_const_context { + if obligation.param_env.constness() == hir::Constness::Const { self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; } else { debug!("passing ~const Drop bound; in non-const context"); @@ -362,9 +362,7 @@ .infcx .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - for predicate_index in result { - candidates.vec.push(ProjectionCandidate(predicate_index)); - } + candidates.vec.extend(result.into_iter().map(ProjectionCandidate)); } /// Given an obligation like ``, searches the obligations that the caller @@ -383,17 +381,19 @@ .param_env .caller_bounds() .iter() - .filter_map(|o| o.to_opt_poly_trait_ref()); + .filter_map(|o| o.to_opt_poly_trait_pred()); // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = - all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); + all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - let wc = self.evaluate_where_clause(stack, bound.value)?; + // FIXME(oli-obk): it is suspicious that we are dropping the constness and + // polarity here. + let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?; if wc.may_apply() { - candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity()))); + candidates.vec.push(ParamCandidate(bound)); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs 2022-02-23 04:07:21.000000000 +0000 @@ -8,12 +8,13 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; +use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty}; -use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; +use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; @@ -51,6 +52,38 @@ obligation: &TraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { + let mut obligation = obligation; + let new_obligation; + + // HACK(const_trait_impl): the surrounding environment is remapped to a non-const context + // because nested obligations might be actually `~const` then (incorrectly) requiring + // const impls. for example: + // ``` + // pub trait Super {} + // pub trait Sub: Super {} + // + // impl const Super for &A where A: ~const Super {} + // impl const Sub for &A where A: ~const Sub {} + // ``` + // + // The procedure to check the code above without the remapping code is as follows: + // ``` + // CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env + // CheckPredicate(&A: Super) + // CheckPredicate(A: ~const Super) // <- still const env, failure + // ``` + if obligation.param_env.constness() == Constness::Const + && obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst + { + new_obligation = TraitObligation { + cause: obligation.cause.clone(), + param_env: obligation.param_env.without_const(), + ..*obligation + }; + + obligation = &new_obligation; + } + match candidate { BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); @@ -58,8 +91,9 @@ } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param.0.value); - Ok(ImplSource::Param(obligations, param.0.constness)) + let obligations = + self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); + Ok(ImplSource::Param(obligations, param.skip_binder().constness)) } ImplCandidate(impl_def_id) => { @@ -139,7 +173,7 @@ let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(trait_predicate); + self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { @@ -150,8 +184,9 @@ let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); let candidate = candidate_predicate - .to_opt_poly_trait_ref() - .expect("projection candidate is not a trait predicate"); + .to_opt_poly_trait_pred() + .expect("projection candidate is not a trait predicate") + .map_bound(|t| t.trait_ref); let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -165,7 +200,7 @@ obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value) + .sup(placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -25,9 +25,10 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectionCacheKeyExt; +use crate::traits::ProjectionCacheKey; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -35,11 +36,10 @@ use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; -use rustc_middle::ty::fast_reject; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; @@ -128,9 +128,6 @@ /// and a negative impl allow_negative_impls: bool, - /// Are we in a const context that needs `~const` bounds to be const? - is_in_const_context: bool, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -141,9 +138,9 @@ struct TraitObligationStack<'prev, 'tcx> { obligation: &'prev TraitObligation<'tcx>, - /// The trait ref from `obligation` but "freshened" with the + /// The trait predicate from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, /// Starts out equal to `depth` -- if, during evaluation, we /// encounter a cycle, then we will set this flag to the minimum @@ -222,7 +219,6 @@ intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -234,7 +230,6 @@ intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -250,7 +245,6 @@ intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -266,26 +260,10 @@ intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode, } } - pub fn with_constness( - infcx: &'cx InferCtxt<'cx, 'tcx>, - constness: hir::Constness, - ) -> SelectionContext<'cx, 'tcx> { - SelectionContext { - infcx, - freshener: infcx.freshener_keep_static(), - intercrate: false, - intercrate_ambiguity_causes: None, - allow_negative_impls: false, - is_in_const_context: matches!(constness, hir::Constness::Const), - query_mode: TraitQueryMode::Standard, - } - } - /// Enables tracking of intercrate ambiguity causes. These are /// used in coherence to give improved diagnostics. We don't do /// this until we detect a coherence error because it can lead to @@ -318,20 +296,6 @@ self.intercrate } - /// Returns `true` if the trait predicate is considerd `const` to this selection context. - pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { - matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context - } - - /// Returns `true` if the predicate is considered `const` to - /// this selection context. - pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool { - match pred.kind().skip_binder() { - ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred), - _ => false, - } - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -558,7 +522,11 @@ }, ty::PredicateKind::TypeOutlives(pred) => { - if pred.0.is_known_global() { + // A global type with no late-bound regions can only + // contain the "'static" lifetime (any other lifetime + // would either be late-bound or local), so it is guaranteed + // to outlive any other lifetime + if pred.0.is_global(self.infcx.tcx) && !pred.0.has_late_bound_regions() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) @@ -583,8 +551,54 @@ let project_obligation = obligation.with(data); match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { - self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - self.evaluate_predicates_recursively(previous_stack, subobligations) + 'compute_res: { + // If we've previously marked this projection as 'complete', thne + // use the final cached result (either `EvaluatedToOk` or + // `EvaluatedToOkModuloRegions`), and skip re-evaluating the + // sub-obligations. + if let Some(key) = + ProjectionCacheKey::from_poly_projection_predicate(self, data) + { + if let Some(cached_res) = self + .infcx + .inner + .borrow_mut() + .projection_cache() + .is_complete(key) + { + break 'compute_res Ok(cached_res); + } + } + + self.add_depth( + subobligations.iter_mut(), + obligation.recursion_depth, + ); + let res = self.evaluate_predicates_recursively( + previous_stack, + subobligations, + ); + if let Ok(res) = res { + if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions { + if let Some(key) = + ProjectionCacheKey::from_poly_projection_predicate( + self, data, + ) + { + // If the result is something that we can cache, then mark this + // entry as 'complete'. This will allow us to skip evaluating the + // suboligations at all the next time we evaluate the projection + // predicate. + self.infcx + .inner + .borrow_mut() + .projection_cache() + .complete(key, res); + } + } + } + res + } } Ok(Ok(None)) => Ok(EvaluatedToAmbig), Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur), @@ -712,20 +726,22 @@ } let stack = self.push_stack(previous_stack, &obligation); - let fresh_trait_ref = stack.fresh_trait_ref; + let mut fresh_trait_pred = stack.fresh_trait_pred; + let mut param_env = obligation.param_env; - debug!(?fresh_trait_ref); + fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { + pred.remap_constness(self.tcx(), &mut param_env); + pred + }); - if let Some(result) = self.check_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - ) { + debug!(?fresh_trait_pred); + + if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) { debug!(?result, "CACHE HIT"); return Ok(result); } - if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) { + if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) { debug!(?result, "PROVISIONAL CACHE HIT"); stack.update_reached_depth(result.reached_depth); return Ok(result.result); @@ -750,19 +766,12 @@ let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - dep_node, - result, - ); + self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); - stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| { + stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| { self.insert_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), + param_env, + fresh_trait_pred, dep_node, provisional_result.max(result), ); @@ -772,10 +781,10 @@ debug!( "caching provisionally because {:?} \ is a cycle participant (at depth {}, reached depth {})", - fresh_trait_ref, stack.depth, reached_depth, + fresh_trait_pred, stack.depth, reached_depth, ); - stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result); + stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_pred, result); } Ok(result) @@ -809,7 +818,7 @@ .skip(1) // Skip top-most frame. .find(|prev| { stack.obligation.param_env == prev.obligation.param_env - && stack.fresh_trait_ref == prev.fresh_trait_ref + && stack.fresh_trait_pred == prev.fresh_trait_pred }) .map(|stack| stack.depth) { @@ -872,7 +881,7 @@ // terms of `Fn` etc, but we could probably make this more // precise still. let unbound_input_types = - stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); + stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh()); if stack.obligation.polarity() != ty::ImplPolarity::Negative { // This check was an imperfect workaround for a bug in the old @@ -910,8 +919,8 @@ && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env && self.match_fresh_trait_refs( - stack.fresh_trait_ref, - prev.fresh_trait_ref, + stack.fresh_trait_pred, + prev.fresh_trait_pred, prev.obligation.param_env, ) }) @@ -989,7 +998,7 @@ // not just the lifetime choice for this particular (non-erased) // predicate. // See issue #80691 - if stack.fresh_trait_ref.has_erased_regions() { + if stack.fresh_trait_pred.has_erased_regions() { result = result.max(EvaluatedToOkModuloRegions); } @@ -1000,8 +1009,7 @@ fn check_evaluation_cache( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { // Neither the global nor local cache is aware of intercrate // mode, so don't do any caching. In particular, we might @@ -1013,19 +1021,17 @@ let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) - { + if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) { return Some(res); } } - self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) + self.infcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) } fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1044,23 +1050,19 @@ } if self.can_use_global_caches(param_env) { - if !trait_ref.needs_infer() { - debug!(?trait_ref, ?result, "insert_evaluation_cache global"); + if !trait_pred.needs_infer() { + debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache.insert( - (param_env.and(trait_ref), polarity), - dep_node, - result, - ); + self.tcx().evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); return; } } - debug!(?trait_ref, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result); + debug!(?trait_pred, ?result, "insert_evaluation_cache"); + self.infcx.evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); } /// For various reasons, it's possible for a subobligation @@ -1138,16 +1140,15 @@ for candidate in candidates { // Respect const trait obligations - if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { + if obligation.is_const() { match candidate { // const impl ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} // const param - ParamCandidate(( - ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, - _, - )) => {} + ParamCandidate(trait_pred) + if trait_pred.skip_binder().constness + == ty::BoundConstness::ConstIfConst => {} // auto trait impl AutoImplCandidate(..) => {} // generator, this will raise error in other places @@ -1256,7 +1257,7 @@ fn check_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { // Neither the global nor local cache is aware of intercrate @@ -1267,19 +1268,15 @@ return None; } let tcx = self.tcx(); - let pred = &cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; + let mut pred = cache_fresh_trait_pred.skip_binder(); + pred.remap_constness(tcx, &mut param_env); + if self.can_use_global_caches(param_env) { - if let Some(res) = tcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) - { + if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { return Some(res); } } - self.infcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) + self.infcx.selection_cache.get(¶m_env.and(pred), tcx) } /// Determines whether can we safely cache the result @@ -1317,43 +1314,36 @@ fn insert_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; + let mut pred = cache_fresh_trait_pred.skip_binder(); + + pred.remap_constness(tcx, &mut param_env); if !self.can_cache_candidate(&candidate) { - debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable"); + debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable"); return; } if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this in certain modes. - } else if !trait_ref.needs_infer() { + } else if !pred.needs_infer() { if !candidate.needs_infer() { - debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); + debug!(?pred, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. - tcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + tcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); return; } } } - debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); - self.infcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + debug!(?pred, ?candidate, "insert_candidate_cache local"); + self.infcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); } /// Matches a predicate against the bounds of its self type. @@ -1544,7 +1534,7 @@ // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitRef<'tcx>| { + let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| { cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions() }; @@ -1577,25 +1567,22 @@ | ConstDropCandidate, ) => false, - ( - ParamCandidate((other, other_polarity)), - ParamCandidate((victim, victim_polarity)), - ) => { - let same_except_bound_vars = other.value.skip_binder() - == victim.value.skip_binder() - && other.constness == victim.constness - && other_polarity == victim_polarity - && !other.value.skip_binder().has_escaping_bound_vars(); + (ParamCandidate(other), ParamCandidate(victim)) => { + let same_except_bound_vars = other.skip_binder().trait_ref + == victim.skip_binder().trait_ref + && other.skip_binder().constness == victim.skip_binder().constness + && other.skip_binder().polarity == victim.skip_binder().polarity + && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. - other.value.bound_vars().len() <= victim.value.bound_vars().len() - } else if other.value == victim.value - && victim.constness == ty::BoundConstness::NotConst - && other_polarity == victim_polarity + other.bound_vars().len() <= victim.bound_vars().len() + } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref + && victim.skip_binder().constness == ty::BoundConstness::NotConst + && other.skip_binder().polarity == victim.skip_binder().polarity { // Drop otherwise equivalent non-const candidates in favor of const candidates. true @@ -1625,11 +1612,11 @@ | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(&cand.0.value), + ) => !is_global(cand), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) + is_global(cand) } ( ImplCandidate(_) @@ -1645,7 +1632,7 @@ ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions() + is_global(cand) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) @@ -2149,10 +2136,21 @@ |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { - let simplified_obligation_ty = - fast_reject::simplify_type(self.tcx(), obligation_ty, true); - let simplified_impl_ty = - fast_reject::simplify_type(self.tcx(), impl_ty, false); + // Note, we simplify parameters for the obligation but not the + // impl so that we do not reject a blanket impl but do reject + // more concrete impls if we're searching for `T: Trait`. + let simplified_obligation_ty = fast_reject::simplify_type( + self.tcx(), + obligation_ty, + SimplifyParams::Yes, + StripReferences::No, + ); + let simplified_impl_ty = fast_reject::simplify_type( + self.tcx(), + impl_ty, + SimplifyParams::No, + StripReferences::No, + ); simplified_obligation_ty.is_some() && simplified_impl_ty.is_some() @@ -2205,8 +2203,8 @@ fn match_fresh_trait_refs( &self, - previous: ty::ConstnessAnd>, - current: ty::ConstnessAnd>, + previous: ty::PolyTraitPredicate<'tcx>, + current: ty::PolyTraitPredicate<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); @@ -2218,17 +2216,13 @@ previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation - .predicate - .to_poly_trait_ref() - .fold_with(&mut self.freshener) - .with_constness(obligation.predicate.skip_binder().constness); + let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener); let dfn = previous_stack.cache.next_dfn(); let depth = previous_stack.depth() + 1; TraitObligationStack { obligation, - fresh_trait_ref, + fresh_trait_pred, reached_depth: Cell::new(depth), previous: previous_stack, dfn, @@ -2389,7 +2383,7 @@ // by using -Z verbose or just a CLI argument. let derived_cause = DerivedObligationCause { parent_trait_ref: obligation.predicate.to_poly_trait_ref(), - parent_code: Lrc::new(obligation.cause.code.clone()), + parent_code: obligation.cause.clone_code(), }; let derived_code = variant(derived_cause); ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code) @@ -2422,7 +2416,7 @@ debug!(reached_depth, "update_reached_depth"); let mut p = self; while reached_depth < p.depth { - debug!(?p.fresh_trait_ref, "update_reached_depth: marking as cycle participant"); + debug!(?p.fresh_trait_pred, "update_reached_depth: marking as cycle participant"); p.reached_depth.set(p.reached_depth.get().min(reached_depth)); p = p.previous.head.unwrap(); } @@ -2501,7 +2495,7 @@ /// - then we determine that `E` is in error -- we will then clear /// all cache values whose DFN is >= 4 -- in this case, that /// means the cached value for `F`. - map: RefCell>, ProvisionalEvaluation>>, + map: RefCell, ProvisionalEvaluation>>, } /// A cache value for the provisional cache: contains the depth-first @@ -2533,28 +2527,28 @@ /// `reached_depth` (from the returned value). fn get_provisional( &self, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { debug!( - ?fresh_trait_ref, + ?fresh_trait_pred, "get_provisional = {:#?}", - self.map.borrow().get(&fresh_trait_ref), + self.map.borrow().get(&fresh_trait_pred), ); - Some(*self.map.borrow().get(&fresh_trait_ref)?) + Some(*self.map.borrow().get(&fresh_trait_pred)?) } /// Insert a provisional result into the cache. The result came /// from the node with the given DFN. It accessed a minimum depth - /// of `reached_depth` to compute. It evaluated `fresh_trait_ref` + /// of `reached_depth` to compute. It evaluated `fresh_trait_pred` /// and resulted in `result`. fn insert_provisional( &self, from_dfn: usize, reached_depth: usize, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, result: EvaluationResult, ) { - debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional"); + debug!(?from_dfn, ?fresh_trait_pred, ?result, "insert_provisional"); let mut map = self.map.borrow_mut(); @@ -2578,7 +2572,7 @@ } } - map.insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, reached_depth, result }); + map.insert(fresh_trait_pred, ProvisionalEvaluation { from_dfn, reached_depth, result }); } /// Invoked when the node with dfn `dfn` does not get a successful @@ -2629,16 +2623,16 @@ fn on_completion( &self, dfn: usize, - mut op: impl FnMut(ty::ConstnessAnd>, EvaluationResult), + mut op: impl FnMut(ty::PolyTraitPredicate<'tcx>, EvaluationResult), ) { debug!(?dfn, "on_completion"); - for (fresh_trait_ref, eval) in + for (fresh_trait_pred, eval) in self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn) { - debug!(?fresh_trait_ref, ?eval, "on_completion"); + debug!(?fresh_trait_pred, ?eval, "on_completion"); - op(fresh_trait_ref, eval.result); + op(fresh_trait_pred, eval.result); } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -508,9 +508,9 @@ Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); for (p, _) in predicates { - if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { - if Some(poly_trait_ref.value.def_id()) == sized_trait { - types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder()); + if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() { + if Some(poly_trait_ref.def_id()) == sized_trait { + types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder()); continue; } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,7 +2,7 @@ use crate::traits; use rustc_hir::def_id::DefId; -use rustc_middle::ty::fast_reject::{self, SimplifiedType}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; @@ -32,7 +32,7 @@ ShouldRecurseOn(DefId), } -trait ChildrenExt { +trait ChildrenExt<'tcx> { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); @@ -44,11 +44,16 @@ ) -> Result; } -impl ChildrenExt for Children { +impl ChildrenExt<'_> for Children { /// Insert an impl into this set of children without comparing to any existing impls. - fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { + fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -60,10 +65,15 @@ /// Removes an impl from this set of children. Used when replacing /// an impl with a parent. The impl must be present in the list of /// children already. - fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { + fn remove_existing(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let vec: &mut Vec; - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -79,7 +89,7 @@ /// specialization relationships. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, simplified_self: Option, ) -> Result { @@ -261,12 +271,12 @@ /// information about the area of overlap is returned in the `Err`. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, ) -> Result, OverlapError>; /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'_>, parent: DefId, child: DefId); } impl GraphExt for Graph { @@ -275,7 +285,7 @@ /// information about the area of overlap is returned in the `Err`. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, ) -> Result, OverlapError> { assert!(impl_def_id.is_local()); @@ -306,7 +316,12 @@ let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false); + let simplified = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); // Descend the specialization tree, where `parent` is the current parent node. loop { @@ -370,7 +385,7 @@ } /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) { + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'_>, parent: DefId, child: DefId) { if self.parent.insert(child, parent).is_some() { bug!( "When recording an impl from the crate store, information about its parent \ diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/structural_match.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/structural_match.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/structural_match.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/structural_match.rs 2022-02-23 04:07:21.000000000 +0000 @@ -66,7 +66,7 @@ /// /// Note that this does *not* recursively check if the substructure of `adt_ty` /// implements the traits. -fn type_marked_structural( +fn type_marked_structural<'tcx>( infcx: &InferCtxt<'_, 'tcx>, adt_ty: Ty<'tcx>, cause: ObligationCause<'tcx>, @@ -119,7 +119,7 @@ seen: FxHashSet, } -impl Search<'a, 'tcx> { +impl<'a, 'tcx> Search<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/util.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/util.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/util.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/util.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::{self, util::*}; @@ -126,8 +126,8 @@ let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) + .to_opt_poly_trait_pred() + .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone()); @@ -172,7 +172,7 @@ } } -impl Iterator for SupertraitDefIds<'tcx> { +impl Iterator for SupertraitDefIds<'_> { type Item = DefId; fn next(&mut self) -> Option { @@ -183,8 +183,8 @@ predicates .predicates .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.value.def_id()) + .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()) + .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); Some(def_id) @@ -232,7 +232,7 @@ debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| { - let cause = match cause.code { + let cause = match *cause.code() { traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new( cause.span, cause.body_id, @@ -259,7 +259,7 @@ } } -pub fn predicate_for_trait_def( +pub fn predicate_for_trait_def<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, @@ -276,7 +276,7 @@ /// Casts a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. -pub fn upcast_choices( +pub fn upcast_choices<'tcx>( tcx: TyCtxt<'tcx>, source_trait_ref: ty::PolyTraitRef<'tcx>, target_trait_def_id: DefId, @@ -291,7 +291,10 @@ /// Given a trait `trait_ref`, returns the number of vtable entries /// that come from `trait_ref`, excluding its supertraits. Used in /// computing the vtable base for an upcast trait of a trait object. -pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize { +pub fn count_own_vtable_entries<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, +) -> usize { let existential_trait_ref = trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); let existential_trait_ref = tcx.erase_regions(existential_trait_ref); @@ -301,7 +304,7 @@ /// Given an upcast trait object described by `object`, returns the /// index of the method `method_def_id` (which should be part of /// `object.upcast_trait_ref`) within the vtable for `object`. -pub fn get_vtable_index_of_object_method( +pub fn get_vtable_index_of_object_method<'tcx, N>( tcx: TyCtxt<'tcx>, object: &super::ImplSourceObjectData<'tcx, N>, method_def_id: DefId, @@ -323,7 +326,7 @@ object.vtable_base + index } -pub fn closure_trait_ref_and_return_type( +pub fn closure_trait_ref_and_return_type<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, @@ -342,7 +345,7 @@ sig.map_bound(|sig| (trait_ref, sig.output())) } -pub fn generator_trait_ref_and_outputs( +pub fn generator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/wf.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/wf.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/wf.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_trait_selection/src/traits/wf.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,12 +1,11 @@ use crate::infer::InferCtxt; use crate::opaque_types::required_region_bounds; use crate::traits; -use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use std::iter; @@ -227,7 +226,7 @@ if let Some(impl_item_span) = items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span) { - cause.make_mut().span = impl_item_span; + cause.span = impl_item_span; } } } @@ -242,7 +241,7 @@ items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span) }) { - cause.make_mut().span = impl_item_span; + cause.span = impl_item_span; } } } @@ -298,12 +297,13 @@ let extend = |obligation: traits::PredicateObligation<'tcx>| { let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { + if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() { let derived_cause = traits::DerivedObligationCause { - parent_trait_ref: parent_trait_ref.value, - parent_code: Lrc::new(obligation.cause.code.clone()), + // FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate + parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref), + parent_code: obligation.cause.clone_code(), }; - cause.make_mut().code = + *cause.make_mut_code() = traits::ObligationCauseCode::DerivedObligation(derived_cause); } extend_cause_with_original_assoc_item_obligation( @@ -342,7 +342,7 @@ if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = item.map(|i| &i.kind) { - new_cause.make_mut().span = self_ty.span; + new_cause.span = self_ty.span; } } traits::Obligation::with_depth( diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/errors.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/errors.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/errors.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/errors.rs 2022-02-23 04:07:21.000000000 +0000 @@ -92,7 +92,7 @@ &self, span: Span, trait_def_id: DefId, - trait_segment: &'a hir::PathSegment<'a>, + trait_segment: &'_ hir::PathSegment<'_>, ) { let trait_def = self.tcx().trait_def(trait_def_id); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/generics.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/generics.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/generics.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/generics.rs 2022-02-23 04:07:21.000000000 +0000 @@ -104,7 +104,7 @@ GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), GenericParamDefKind::Const { .. }, ) if tcx.type_of(param.def_id) == tcx.types.usize => { - let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); + let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id())); if let Ok(snippet) = snippet { err.span_suggestion( arg.span(), @@ -131,8 +131,8 @@ _ => {} } - let kind_ord = param.kind.to_ord(tcx); - let arg_ord = arg.to_ord(tcx.features()); + let kind_ord = param.kind.to_ord(); + let arg_ord = arg.to_ord(); // This note is only true when generic parameters are strictly ordered by their kind. if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { @@ -298,26 +298,7 @@ .params .clone() .into_iter() - .map(|param| { - ( - match param.kind { - GenericParamDefKind::Lifetime => { - ParamKindOrd::Lifetime - } - GenericParamDefKind::Type { .. } => { - ParamKindOrd::Type - } - GenericParamDefKind::Const { .. } => { - ParamKindOrd::Const { - unordered: tcx - .features() - .unordered_const_ty_params(), - } - } - }, - param, - ) - }) + .map(|param| (param.kind.to_ord(), param)) .collect::>(); param_types_present.sort_by_key(|(ord, _)| *ord); let (mut param_types_present, ordered_params): ( @@ -330,16 +311,7 @@ tcx, arg, param, - !args_iter.clone().is_sorted_by_key(|arg| match arg { - GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, - GenericArg::Type(_) => ParamKindOrd::Type, - GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx - .features() - .unordered_const_ty_params(), - }, - GenericArg::Infer(_) => ParamKindOrd::Infer, - }), + !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()), Some(&format!( "reorder the arguments: {}: `<{}>`", param_types_present diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/astconv/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,6 +13,7 @@ }; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; +use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError}; use rustc_hir as hir; @@ -24,7 +25,8 @@ use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; +use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; +use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -35,7 +37,6 @@ use rustc_trait_selection::traits::wf::object_region_bounds; use smallvec::SmallVec; -use std::array; use std::collections::BTreeSet; use std::slice; @@ -415,34 +416,40 @@ arg: &GenericArg<'_>, ) -> subst::GenericArg<'tcx> { let tcx = self.astconv.tcx(); + + let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| { + if has_default { + tcx.check_optional_stability( + param.def_id, + Some(arg.id()), + arg.span(), + None, + |_, _| { + // Default generic parameters may not be marked + // with stability attributes, i.e. when the + // default parameter was defined at the same time + // as the rest of the type. As such, we ignore missing + // stability attributes. + }, + ) + } + if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { + self.inferred_params.push(ty.span); + tcx.ty_error().into() + } else { + self.astconv.ast_ty_to_ty(ty).into() + } + }; + match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { self.astconv.ast_region_to_region(lt, Some(param)).into() } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { - if has_default { - tcx.check_optional_stability( - param.def_id, - Some(arg.id()), - arg.span(), - None, - |_, _| { - // Default generic parameters may not be marked - // with stability attributes, i.e. when the - // default parameter was defined at the same time - // as the rest of the type. As such, we ignore missing - // stability attributes. - }, - ) - } - if let (hir::TyKind::Infer, false) = - (&ty.kind, self.astconv.allow_ty_infer()) - { - self.inferred_params.push(ty.span); - tcx.ty_error().into() - } else { - self.astconv.ast_ty_to_ty(ty).into() - } + handle_ty_args(has_default, ty) + } + (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { + handle_ty_args(has_default, &inf.to_ty()) } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { ty::Const::from_opt_const_arg_anon_const( @@ -454,41 +461,13 @@ ) .into() } - (&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => { - if has_default { - tcx.const_param_default(param.def_id).into() - } else if self.astconv.allow_ty_infer() { - // FIXME(const_generics): Actually infer parameter here? - todo!() - } else { - self.inferred_params.push(inf.span); - tcx.ty_error().into() - } - } - ( - &GenericParamDefKind::Type { has_default, .. }, - hir::GenericArg::Infer(inf), - ) => { - if has_default { - tcx.check_optional_stability( - param.def_id, - Some(arg.id()), - arg.span(), - None, - |_, _| { - // Default generic parameters may not be marked - // with stability attributes, i.e. when the - // default parameter was defined at the same time - // as the rest of the type. As such, we ignore missing - // stability attributes. - }, - ); - } + (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { + let ty = tcx.at(self.span).type_of(param.def_id); if self.astconv.allow_ty_infer() { - self.astconv.ast_ty_to_ty(&inf.to_ty()).into() + self.astconv.ct_infer(ty, Some(param), inf.span).into() } else { self.inferred_params.push(inf.span); - tcx.ty_error().into() + tcx.const_error(ty).into() } } _ => unreachable!(), @@ -1351,7 +1330,7 @@ tcx, span, item.trait_ref().def_id(), - &object_safety_violations[..], + &object_safety_violations, ) .emit(); return tcx.ty_error(); @@ -1588,7 +1567,7 @@ traits::transitive_bounds_that_define_assoc_type( tcx, predicates.iter().filter_map(|(p, _)| { - p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) + Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) }), assoc_name, ) @@ -1635,7 +1614,7 @@ debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); let is_equality = is_equality(); - let bounds = array::IntoIter::new([bound, bound2]).chain(matching_candidates); + let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); let mut err = if is_equality.is_some() { // More specific Error Index entry. struct_span_err!( @@ -2289,13 +2268,19 @@ /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { - self.ast_ty_to_ty_inner(ast_ty, false) + self.ast_ty_to_ty_inner(ast_ty, false, false) + } + + /// Parses the programmer's textual representation of a type into our + /// internal notion of a type. This is meant to be used within a path. + pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + self.ast_ty_to_ty_inner(ast_ty, false, true) } /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[tracing::instrument(level = "debug", skip(self))] - fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> { + fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match ast_ty.kind { @@ -2306,7 +2291,7 @@ hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); - let t = self.ast_ty_to_ty_inner(mt.ty, true); + let t = self.ast_ty_to_ty_inner(mt.ty, true, false); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, @@ -2325,6 +2310,7 @@ )) } hir::TyKind::TraitObject(bounds, ref lifetime, _) => { + self.maybe_lint_bare_trait(ast_ty, in_path); self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { @@ -2337,15 +2323,22 @@ let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some()) - } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self + .impl_trait_ty_to_ty( + def_id, + lifetimes, + matches!( + origin, + hir::OpaqueTyOrigin::FnReturn(..) + | hir::OpaqueTyOrigin::AsyncFn(..) + ), + ), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); - let ty = self.ast_ty_to_ty(qself); + let ty = self.ast_ty_to_ty_inner(qself, false, true); let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = qself.kind { path.res @@ -2356,7 +2349,7 @@ .map(|(ty, _, _)| ty) .unwrap_or_else(|_| tcx.ty_error()) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); let (substs, _) = self.create_substs_for_ast_path( span, @@ -2370,8 +2363,14 @@ self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs)) } hir::TyKind::Array(ref ty, ref length) => { - let length_def_id = tcx.hir().local_def_id(length.hir_id); - let length = ty::Const::from_anon_const(tcx, length_def_id); + let length = match length { + &hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span), + hir::ArrayLen::Body(constant) => { + let length_def_id = tcx.hir().local_def_id(constant.hir_id); + ty::Const::from_anon_const(tcx, length_def_id) + } + }; + let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); self.normalize_ty(ast_ty.span, array_ty) } @@ -2602,4 +2601,62 @@ } Some(r) } + + fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { + let tcx = self.tcx(); + if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + { + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(self_ty.span) + .ok() + .map_or(false, |s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + let sugg = Vec::from_iter([ + ( + self_ty.span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + ), + ( + self_ty.span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + ), + ]); + if self_ty.span.edition() >= Edition::Edition2021 { + let msg = "trait objects must include the `dyn` keyword"; + let label = "add `dyn` keyword before this trait"; + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg) + .multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable) + .emit(); + } else { + let msg = "trait objects without an explicit `dyn` are deprecated"; + tcx.struct_span_lint_hir( + BARE_TRAIT_OBJECTS, + self_ty.hir_id, + self_ty.span, + |lint| { + lint.build(msg) + .multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ) + .emit() + }, + ); + } + } + } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/bounds.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/bounds.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/bounds.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/bounds.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,7 +1,7 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; /// Collects together a list of type bounds. These lists of bounds occur in many places diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/callee.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/callee.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/callee.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/callee.rs 2022-02-23 04:07:21.000000000 +0000 @@ -496,7 +496,7 @@ call_expr.span, call_expr, fn_sig.inputs(), - &expected_arg_tys[..], + expected_arg_tys, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::DontTupleArguments, @@ -529,7 +529,7 @@ call_expr.span, call_expr, fn_sig.inputs(), - &expected_arg_tys, + expected_arg_tys, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::TupleArguments, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/cast.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/cast.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/cast.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/cast.rs 2022-02-23 04:07:21.000000000 +0000 @@ -638,7 +638,11 @@ self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty); self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty); - if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) { + debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); + + if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) + && !self.cast_ty.has_infer_types() + { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/check.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/check.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/check.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/check.rs 2022-02-23 04:07:21.000000000 +0000 @@ -453,12 +453,12 @@ /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result /// in "inheriting lifetimes". #[instrument(level = "debug", skip(tcx, span))] -pub(super) fn check_opaque_for_inheriting_lifetimes( +pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span, ) { - let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id)); + let item = tcx.hir().expect_item(def_id); debug!(?item, ?span); struct FoundParentLifetime; @@ -517,7 +517,7 @@ } } - impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { type Map = rustc_middle::hir::map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { @@ -541,7 +541,7 @@ } if let ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) = item.kind { @@ -567,7 +567,7 @@ visitor.visit_item(&item); let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn) + matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) } _ => unreachable!(), }; @@ -604,7 +604,7 @@ ) -> Result<(), ErrorReported> { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { - hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), + hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -635,7 +635,7 @@ ) { match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => {} } @@ -730,7 +730,7 @@ let abi = sig.header.abi; fn_maybe_err(tcx, item.ident.span, abi); } - hir::TraitItemKind::Type(.., Some(_default)) => { + hir::TraitItemKind::Type(.., Some(default)) => { let assoc_item = tcx.associated_item(item.def_id); let trait_substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); @@ -738,7 +738,7 @@ tcx, assoc_item, assoc_item, - item.span, + default.span, ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, ); } @@ -987,12 +987,12 @@ opt_trait_span, ); } - hir::ImplItemKind::TyAlias(_) => { + hir::ImplItemKind::TyAlias(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); compare_ty_impl( tcx, &ty_impl_item, - impl_item.span, + impl_ty.span, &ty_trait_item, impl_trait_ref, opt_trait_span, @@ -1506,19 +1506,13 @@ tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); } -pub(super) fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_item_well_formed(tcx, def_id); -} +pub(super) use wfcheck::check_item_well_formed; -pub(super) fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_trait_item(tcx, def_id); -} +pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed; -pub(super) fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_impl_item(tcx, def_id); -} +pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed; -fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) { +fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) { struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing") .span_label(span, "recursive `async fn`") .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") @@ -1536,7 +1530,7 @@ /// /// If all the return expressions evaluate to `!`, then we explain that the error will go away /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. -fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { +fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type"); let mut label = false; diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/closure.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/closure.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/closure.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/closure.rs 2022-02-23 04:07:21.000000000 +0000 @@ -80,7 +80,7 @@ let generator_types = check_fn( self, - self.param_env, + self.param_env.without_const(), liberated_sig, decl, expr.hir_id, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/coercion.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/coercion.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/coercion.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/coercion.rs 2022-02-23 04:07:21.000000000 +0000 @@ -102,7 +102,7 @@ vec![] } -fn simple(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { +fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -1126,8 +1126,10 @@ for expr in exprs { let expr = expr.as_coercion_site(); let noop = match self.typeck_results.borrow().expr_adjustments(expr) { - &[Adjustment { kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }] => - { + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }, + ] => { match *self.node_ty(expr.hir_id).kind() { ty::Ref(_, _, mt_orig) => { let mutbl_adj: hir::Mutability = mutbl_adj.into(); @@ -1442,7 +1444,7 @@ let mut err; let mut unsized_return = false; - match cause.code { + match *cause.code() { ObligationCauseCode::ReturnNoExpression => { err = struct_span_err!( fcx.tcx.sess, @@ -1637,11 +1639,10 @@ let ty = >::ast_ty_to_ty(fcx, ty); // Get the `impl Trait`'s `DefId`. if let ty::Opaque(def_id, _) = ty.kind() { - let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); // Get the `impl Trait`'s `Item` so that we can get its trait bounds and // get the `Trait`'s `DefId`. if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) = - fcx.tcx.hir().expect_item(hir_id).kind + fcx.tcx.hir().expect_item(def_id.expect_local()).kind { // Are of this `impl Trait`'s traits object safe? is_object_safe = bounds.iter().all(|bound| { @@ -1693,7 +1694,7 @@ err.help("you could instead create a new `enum` with a variant for each returned type"); } - fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { + fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(fcx, ty); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/compare_method.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/compare_method.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/compare_method.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/compare_method.rs 2022-02-23 04:07:21.000000000 +0000 @@ -208,8 +208,11 @@ // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause); @@ -229,7 +232,7 @@ inh.register_predicates(obligations); let mut cause = cause.clone(); - cause.make_mut().span = span; + cause.span = span; inh.register_predicate(traits::Obligation::new(cause, param_env, predicate)); } @@ -290,7 +293,7 @@ let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m); - cause.make_mut().span = impl_err_span; + cause.span = impl_err_span; let mut diag = struct_span_err!( tcx.sess, @@ -317,9 +320,7 @@ // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole // argument pattern and type. - let impl_m_hir_id = - tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + 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) @@ -341,9 +342,7 @@ 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. - let impl_m_hir_id = - tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref sig, _) if sig.header.asyncness == hir::IsAsync::NotAsync => { @@ -383,6 +382,7 @@ found: impl_fty, })), &terr, + false, ); diag.emit(); return Err(ErrorReported); @@ -462,22 +462,19 @@ trait_m: &ty::AssocItem, ) -> (Span, Option) { let tcx = infcx.tcx; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref sig, _) => { sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } _ => bug!("{:?} is not a method", impl_m), }; - let trait_args = trait_m.def_id.as_local().map(|def_id| { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().expect_trait_item(trait_m_hir_id).kind { + let trait_args = + trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind { TraitItemKind::Fn(ref sig, _) => { sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - } - }); + }); match *terr { TypeError::ArgumentMutability(i) => { @@ -595,8 +592,7 @@ err_occurred = true; let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() { - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_item = tcx.hir().expect_trait_item(trait_hir_id); + let trait_item = tcx.hir().expect_trait_item(def_id); if trait_item.generics.params.is_empty() { (Some(vec![trait_item.generics.span]), vec![]) } else { @@ -617,8 +613,7 @@ (trait_span.map(|s| vec![s]), vec![]) }; - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local()); - let impl_item = tcx.hir().expect_impl_item(impl_hir_id); + let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local()); let impl_item_impl_trait_spans: Vec = impl_item .generics .params @@ -706,8 +701,7 @@ let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { let trait_span = if let Some(def_id) = trait_m.def_id.as_local() { - let trait_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().expect_trait_item(trait_id).kind { + match tcx.hir().expect_trait_item(def_id).kind { TraitItemKind::Fn(ref trait_m_sig, _) => { let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 }; if let Some(arg) = trait_m_sig.decl.inputs.get(pos) { @@ -725,8 +719,7 @@ } else { trait_item_span }; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref impl_m_sig, _) => { let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 }; if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { @@ -745,8 +738,7 @@ tcx.sess, impl_span, E0050, - "method `{}` has {} but the declaration in \ - trait `{}` has {}", + "method `{}` has {} but the declaration in trait `{}` has {}", trait_m.ident, potentially_plural_count(impl_number_args, "parameter"), tcx.def_path_str(trait_m.def_id), @@ -1050,8 +1042,8 @@ ); // Locate the Span containing just the type of the offending impl - match tcx.hir().expect_impl_item(impl_c_hir_id).kind { - ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span, + match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind { + ImplItemKind::Const(ref ty, _) => cause.span = ty.span, _ => bug!("{:?} is not a impl const", impl_c), } @@ -1063,11 +1055,9 @@ trait_c.ident ); - let trait_c_hir_id = - trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); - let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| { + let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| { // Add a label to the Span containing just the type of the const - match tcx.hir().expect_trait_item(trait_c_hir_id).kind { + match tcx.hir().expect_trait_item(trait_c_def_id).kind { TraitItemKind::Const(ref ty, _) => ty.span, _ => bug!("{:?} is not a trait const", trait_c), } @@ -1082,6 +1072,7 @@ found: impl_ty, })), &terr, + false, ); diag.emit(); } @@ -1112,7 +1103,8 @@ let _: Result<(), ErrorReported> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; + let sp = tcx.def_span(impl_ty.def_id); + compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?; check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); @@ -1178,8 +1170,11 @@ debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error( tcx, impl_ty.def_id, @@ -1364,7 +1359,11 @@ .to_predicate(tcx), ), }; - ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + Reveal::UserFacing, + param_env.constness(), + ) }; debug!(?normalize_param_env); @@ -1373,13 +1372,7 @@ impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); tcx.infer_ctxt().enter(move |infcx| { - let constness = impl_ty - .container - .impl_def_id() - .map(|did| tcx.impl_constness(did)) - .unwrap_or(hir::Constness::NotConst); - - let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness); + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; let mut selcx = traits::SelectionContext::new(&infcx); @@ -1423,8 +1416,7 @@ // Check that all obligations are satisfied by the implementation's // version. - let errors = - inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/demand.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/demand.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/demand.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/demand.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1223,7 +1223,7 @@ // Missing try_into implementation for `{integer}` to `{float}` err.multipart_suggestion_verbose( &format!( - "{}, producing the floating point representation of the integer, + "{}, producing the floating point representation of the integer, \ rounded if necessary", cast_msg, ), @@ -1264,6 +1264,18 @@ } true } + ( + &ty::Uint(ty::UintTy::U32 | ty::UintTy::U64 | ty::UintTy::U128) + | &ty::Int(ty::IntTy::I32 | ty::IntTy::I64 | ty::IntTy::I128), + &ty::Char, + ) => { + err.multipart_suggestion_verbose( + &format!("{}, since a `char` always occupies 4 bytes", cast_msg,), + cast_suggestion, + Applicability::MachineApplicable, + ); + true + } _ => false, } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/dropck.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/dropck.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/dropck.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/dropck.rs 2022-02-23 04:07:21.000000000 +0000 @@ -302,7 +302,7 @@ } } -impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { +impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/expr.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/expr.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/expr.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/expr.rs 2022-02-23 04:07:21.000000000 +0000 @@ -36,8 +36,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; +use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts}; -use rustc_middle::ty::relate::expected_found_bool; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; use rustc_session::parse::feature_err; @@ -46,6 +46,7 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::{BytePos, Pos}; use rustc_trait_selection::traits::{self, ObligationCauseCode}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -276,8 +277,8 @@ ExprKind::AddrOf(kind, mutbl, oprnd) => { self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) } - ExprKind::Path(QPath::LangItem(lang_item, _)) => { - self.check_lang_item_path(lang_item, expr) + ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { + self.check_lang_item_path(lang_item, expr, hir_id) } ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), ExprKind::InlineAsm(asm) => self.check_expr_asm(asm), @@ -299,7 +300,7 @@ } } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), - ExprKind::Let(pat, let_expr, _) => self.check_expr_let(let_expr, pat), + ExprKind::Let(let_expr) => self.check_expr_let(let_expr), ExprKind::Loop(body, _, source, _) => { self.check_expr_loop(body, source, expected, expr) } @@ -497,8 +498,9 @@ &self, lang_item: hir::LangItem, expr: &'tcx hir::Expr<'tcx>, + hir_id: Option, ) -> Ty<'tcx> { - self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 + self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 } pub(crate) fn check_expr_path( @@ -876,11 +878,6 @@ "let ".to_string(), Applicability::MachineApplicable, ); - if !self.sess().features_untracked().destructuring_assignment { - // We already emit an E0658 with a suggestion for `while let`, this is - // redundant output. - err.delay_as_bug(); - } break; } hir::Node::Item(_) @@ -1047,10 +1044,13 @@ } } - fn check_expr_let(&self, expr: &'tcx hir::Expr<'tcx>, pat: &'tcx hir::Pat<'tcx>) -> Ty<'tcx> { - self.warn_if_unreachable(expr.hir_id, expr.span, "block in `let` expression"); - let expr_ty = self.demand_scrutinee_type(expr, pat.contains_explicit_ref_binding(), false); - self.check_pat_top(pat, expr_ty, Some(expr.span), true); + fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { + // for let statements, this is done in check_stmt + let init = let_expr.init; + self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); + // otherwise check exactly as a let statement + self.check_decl(let_expr.into()); + // but return a bool, for this is a boolean expression self.tcx.types.bool } @@ -1238,12 +1238,12 @@ fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::AnonConst, + count: &'tcx hir::ArrayLen, expected: Expectation<'tcx>, _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count = self.to_const(count); + let count = self.array_length_to_const(count); let uty = match expected { ExpectHasType(uty) => match *uty.kind() { @@ -1493,7 +1493,7 @@ &self.misc(base_expr.span), adt_ty, base_ty, - Sorts(expected_found_bool(true, adt_ty, base_ty)), + Sorts(ExpectedFound::new(true, adt_ty, base_ty)), ) .emit(); } @@ -1508,7 +1508,7 @@ } } else { self.check_expr_has_type_or_error(base_expr, adt_ty, |_| { - let base_ty = self.check_expr(base_expr); + let base_ty = self.typeck_results.borrow().node_type(base_expr.hir_id); let same_adt = match (adt_ty.kind(), base_ty.kind()) { (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true, _ => false, @@ -2063,7 +2063,36 @@ Some(span), ); } else { - err.help("methods are immutable and cannot be assigned to"); + let mut found = false; + + if let ty::RawPtr(ty_and_mut) = expr_t.kind() { + if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() { + if adt_def.variants.len() == 1 + && adt_def + .variants + .iter() + .next() + .unwrap() + .fields + .iter() + .any(|f| f.ident == field) + { + if let Some(dot_loc) = expr_snippet.rfind('.') { + found = true; + err.span_suggestion( + expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)), + "to access the field, dereference first", + format!("(*{})", &expr_snippet[0..dot_loc]), + Applicability::MaybeIncorrect, + ); + } + } + } + } + + if !found { + err.help("methods are immutable and cannot be assigned to"); + } } err.emit(); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs 2022-02-23 04:07:21.000000000 +0000 @@ -1,5 +1,6 @@ use crate::astconv::AstConv; use crate::check::coercion::CoerceMany; +use crate::check::gather_locals::Declaration; use crate::check::method::MethodCallee; use crate::check::Expectation::*; use crate::check::TupleArgumentsFlag::*; @@ -54,14 +55,14 @@ let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], + TupleArguments => vec![self.tcx.intern_tup(&err_inputs)], }; self.check_argument_types( sp, expr, - &err_inputs[..], - &[], + &err_inputs, + vec![], args_no_rcvr, false, tuple_arguments, @@ -72,7 +73,7 @@ let method = method.unwrap(); // HACK(eddyb) ignore self in the definition (see above). - let expected_arg_tys = self.expected_inputs_for_expected_output( + let expected_input_tys = self.expected_inputs_for_expected_output( sp, expected, method.sig.output(), @@ -82,7 +83,7 @@ sp, expr, &method.sig.inputs()[1..], - &expected_arg_tys[..], + expected_input_tys, args_no_rcvr, method.sig.c_variadic, tuple_arguments, @@ -95,34 +96,43 @@ /// method calls and overloaded operators. pub(in super::super) fn check_argument_types( &self, - sp: Span, - expr: &'tcx hir::Expr<'tcx>, - fn_inputs: &[Ty<'tcx>], - expected_arg_tys: &[Ty<'tcx>], - args: &'tcx [hir::Expr<'tcx>], + // Span enclosing the call site + call_span: Span, + // Expression of the call site + call_expr: &'tcx hir::Expr<'tcx>, + // Types (as defined in the *signature* of the target function) + formal_input_tys: &[Ty<'tcx>], + // More specific expected types, after unifying with caller output types + expected_input_tys: Vec>, + // The expressions for each provided argument + provided_args: &'tcx [hir::Expr<'tcx>], + // Whether the function is variadic, for example when imported from C c_variadic: bool, + // Whether the arguments have been bundled in a tuple (ex: closures) tuple_arguments: TupleArgumentsFlag, - def_id: Option, + // The DefId for the function being called, for better error messages + fn_def_id: Option, ) { let tcx = self.tcx; // Grab the argument types, supplying fresh type variables // if the wrong number of arguments were supplied - let supplied_arg_count = if tuple_arguments == DontTupleArguments { args.len() } else { 1 }; + let supplied_arg_count = + if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 }; // All the input types from the fn signature must outlive the call // so as to validate implied bounds. - for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) { + for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } - let expected_arg_count = fn_inputs.len(); + let expected_arg_count = formal_input_tys.len(); let param_count_error = |expected_count: usize, arg_count: usize, error_code: &str, c_variadic: bool, sugg_unit: bool| { - let (span, start_span, args, ctor_of) = match &expr.kind { + let (span, start_span, args, ctor_of) = match &call_expr.kind { hir::ExprKind::Call( hir::Expr { span, @@ -155,14 +165,14 @@ &args[1..], // Skip the receiver. None, // methods are never ctors ), - k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), + k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k), }; - let arg_spans = if args.is_empty() { + let arg_spans = if provided_args.is_empty() { // foo() // ^^^-- supplied 0 arguments // | // expected 2 arguments - vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())] + vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())] } else { // foo(1, 2, 3) // ^^^ - - - supplied 3 arguments @@ -195,7 +205,7 @@ ); } - if let Some(def_id) = def_id { + if let Some(def_id) = fn_def_id { if let Some(def_span) = tcx.def_ident_span(def_id) { let mut spans: MultiSpan = def_span.into(); @@ -217,7 +227,7 @@ } if sugg_unit { - let sugg_span = tcx.sess.source_map().end_point(expr.span); + let sugg_span = tcx.sess.source_map().end_point(call_expr.span); // remove closing `)` from the span let sugg_span = sugg_span.shrink_to_lo(); err.span_suggestion( @@ -239,110 +249,148 @@ err.emit(); }; - let mut expected_arg_tys = expected_arg_tys.to_vec(); - - let formal_tys = if tuple_arguments == TupleArguments { - let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); + let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { + let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]); match tuple_type.kind() { - ty::Tuple(arg_types) if arg_types.len() != args.len() => { - param_count_error(arg_types.len(), args.len(), "E0057", false, false); - expected_arg_tys = vec![]; - self.err_args(args.len()) + ty::Tuple(arg_types) if arg_types.len() != provided_args.len() => { + param_count_error(arg_types.len(), provided_args.len(), "E0057", false, false); + (self.err_args(provided_args.len()), vec![]) } ty::Tuple(arg_types) => { - expected_arg_tys = match expected_arg_tys.get(0) { + let expected_input_tys = match expected_input_tys.get(0) { Some(&ty) => match ty.kind() { ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), _ => vec![], }, None => vec![], }; - arg_types.iter().map(|k| k.expect_ty()).collect() + (arg_types.iter().map(|k| k.expect_ty()).collect(), expected_input_tys) } _ => { struct_span_err!( tcx.sess, - sp, + call_span, E0059, "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) .emit(); - expected_arg_tys = vec![]; - self.err_args(args.len()) + (self.err_args(provided_args.len()), vec![]) } } } else if expected_arg_count == supplied_arg_count { - fn_inputs.to_vec() + (formal_input_tys.to_vec(), expected_input_tys) } else if c_variadic { if supplied_arg_count >= expected_arg_count { - fn_inputs.to_vec() + (formal_input_tys.to_vec(), expected_input_tys) } else { param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false); - expected_arg_tys = vec![]; - self.err_args(supplied_arg_count) + (self.err_args(supplied_arg_count), vec![]) } } else { // is the missing argument of type `()`? - let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { - self.resolve_vars_if_possible(expected_arg_tys[0]).is_unit() - } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { - self.resolve_vars_if_possible(fn_inputs[0]).is_unit() + let sugg_unit = if expected_input_tys.len() == 1 && supplied_arg_count == 0 { + self.resolve_vars_if_possible(expected_input_tys[0]).is_unit() + } else if formal_input_tys.len() == 1 && supplied_arg_count == 0 { + self.resolve_vars_if_possible(formal_input_tys[0]).is_unit() } else { false }; param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit); - expected_arg_tys = vec![]; - self.err_args(supplied_arg_count) + (self.err_args(supplied_arg_count), vec![]) }; debug!( - "check_argument_types: formal_tys={:?}", - formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::>() + "check_argument_types: formal_input_tys={:?}", + formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::>() ); - // If there is no expectation, expect formal_tys. - let expected_arg_tys = - if !expected_arg_tys.is_empty() { expected_arg_tys } else { formal_tys.clone() }; + // If there is no expectation, expect formal_input_tys. + let expected_input_tys = if !expected_input_tys.is_empty() { + expected_input_tys + } else { + formal_input_tys.clone() + }; + assert_eq!(expected_input_tys.len(), formal_input_tys.len()); + + // Keep track of the fully coerced argument types let mut final_arg_types: Vec<(usize, Ty<'_>, Ty<'_>)> = vec![]; + // We introduce a helper function to demand that a given argument satisfy a given input + // This is more complicated than just checking type equality, as arguments could be coerced + // This version writes those types back so further type checking uses the narrowed types + let demand_compatible = |idx, final_arg_types: &mut Vec<(usize, Ty<'tcx>, Ty<'tcx>)>| { + let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; + let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; + let provided_arg = &provided_args[idx]; + + debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty); + + // The special-cased logic below has three functions: + // 1. Provide as good of an expected type as possible. + let expectation = Expectation::rvalue_hint(self, expected_input_ty); + + let checked_ty = self.check_expr_with_expectation(provided_arg, expectation); + + // 2. Coerce to the most detailed type that could be coerced + // to, which is `expected_ty` if `rvalue_hint` returns an + // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. + let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); + + // Keep track of these for below + final_arg_types.push((idx, checked_ty, coerced_ty)); + + // Cause selection errors caused by resolving a single argument to point at the + // argument and not the call. This is otherwise redundant with the `demand_coerce` + // call immediately after, but it lets us customize the span pointed to in the + // fulfillment error to be more accurate. + let _ = + self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| { + self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); + self.point_at_arg_instead_of_call_if_possible( + errors, + &final_arg_types, + call_expr, + call_span, + provided_args, + ); + }); + + // We're processing function arguments so we definitely want to use + // two-phase borrows. + self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes); + + // 3. Relate the expected type and the formal one, + // if the expected type was used for the coercion. + self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty); + }; + // Check the arguments. // We do this in a pretty awful way: first we type-check any arguments // that are not closures, then we type-check the closures. This is so // that we have more information about the types of arguments when we // type-check the functions. This isn't really the right way to do this. for check_closures in [false, true] { - debug!("check_closures={}", check_closures); - // More awful hacks: before we check argument types, try to do // an "opportunistic" trait resolution of any trait bounds on // the call. This helps coercions. if check_closures { self.select_obligations_where_possible(false, |errors| { - self.point_at_type_arg_instead_of_call_if_possible(errors, expr); + self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); self.point_at_arg_instead_of_call_if_possible( errors, - &final_arg_types[..], - expr, - sp, - &args, + &final_arg_types, + call_expr, + call_span, + &provided_args, ); }) } - // For C-variadic functions, we don't have a declared type for all of - // the arguments hence we only do our usual type checking with - // the arguments who's types we do know. - let t = if c_variadic { - expected_arg_count - } else if tuple_arguments == TupleArguments { - args.len() - } else { - supplied_arg_count - }; - for (i, arg) in args.iter().take(t).enumerate() { + let minimum_input_count = formal_input_tys.len(); + for (idx, arg) in provided_args.iter().enumerate() { // Warn only for the first loop (the "no closures" one). // Closure arguments themselves can't be diverging, but // a previous argument can, e.g., `foo(panic!(), || {})`. @@ -350,53 +398,21 @@ self.warn_if_unreachable(arg.hir_id, arg.span, "expression"); } - let is_closure = matches!(arg.kind, ExprKind::Closure(..)); + // For C-variadic functions, we don't have a declared type for all of + // the arguments hence we only do our usual type checking with + // the arguments who's types we do know. However, we *can* check + // for unreachable expressions (see above). + // FIXME: unreachable warning current isn't emitted + if idx >= minimum_input_count { + continue; + } + let is_closure = matches!(arg.kind, ExprKind::Closure(..)); if is_closure != check_closures { continue; } - let formal_ty = formal_tys[i]; - debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty); - - // The special-cased logic below has three functions: - // 1. Provide as good of an expected type as possible. - let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]); - - let checked_ty = self.check_expr_with_expectation(&arg, expected); - - // 2. Coerce to the most detailed type that could be coerced - // to, which is `expected_ty` if `rvalue_hint` returns an - // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. - let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty); - - final_arg_types.push((i, checked_ty, coerce_ty)); - - // Cause selection errors caused by resolving a single argument to point at the - // argument and not the call. This is otherwise redundant with the `demand_coerce` - // call immediately after, but it lets us customize the span pointed to in the - // fulfillment error to be more accurate. - let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment( - coerce_ty, - |errors| { - self.point_at_type_arg_instead_of_call_if_possible(errors, expr); - self.point_at_arg_instead_of_call_if_possible( - errors, - &final_arg_types, - expr, - sp, - args, - ); - }, - ); - - // We're processing function arguments so we definitely want to use - // two-phase borrows. - self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes); - - // 3. Relate the expected type and the formal one, - // if the expected type was used for the coercion. - self.demand_suptype(arg.span, formal_ty, coerce_ty); + demand_compatible(idx, &mut final_arg_types); } } @@ -409,7 +425,7 @@ MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit() } - for arg in args.iter().skip(expected_arg_count) { + for arg in provided_args.iter().skip(expected_arg_count) { let arg_ty = self.check_expr(&arg); // There are a few types which get autopromoted when passed via varargs @@ -538,16 +554,17 @@ pub fn check_decl_initializer( &self, - local: &'tcx hir::Local<'tcx>, + hir_id: hir::HirId, + pat: &'tcx hir::Pat<'tcx>, init: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed // for #42640 (default match binding modes). // // See #44848. - let ref_bindings = local.pat.contains_explicit_ref_binding(); + let ref_bindings = pat.contains_explicit_ref_binding(); - let local_ty = self.local_ty(init.span, local.hir_id).revealed_ty; + let local_ty = self.local_ty(init.span, hir_id).revealed_ty; if let Some(m) = ref_bindings { // Somewhat subtle: if we have a `ref` binding in the pattern, // we want to avoid introducing coercions for the RHS. This is @@ -565,29 +582,33 @@ } } - /// Type check a `let` statement. - pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { + pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { // Determine and write the type which we'll check the pattern against. - let ty = self.local_ty(local.span, local.hir_id).decl_ty; - self.write_ty(local.hir_id, ty); + let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty; + self.write_ty(decl.hir_id, decl_ty); // Type check the initializer. - if let Some(ref init) = local.init { - let init_ty = self.check_decl_initializer(local, &init); - self.overwrite_local_ty_if_err(local, ty, init_ty); + if let Some(ref init) = decl.init { + let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty); } // Does the expected pattern type originate from an expression and what is the span? - let (origin_expr, ty_span) = match (local.ty, local.init) { + let (origin_expr, ty_span) = match (decl.ty, decl.init) { (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type. (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee. _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained. }; // Type check the pattern. Override if necessary to avoid knock-on errors. - self.check_pat_top(&local.pat, ty, ty_span, origin_expr); - let pat_ty = self.node_ty(local.pat.hir_id); - self.overwrite_local_ty_if_err(local, ty, pat_ty); + self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); + let pat_ty = self.node_ty(decl.pat.hir_id); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty); + } + + /// Type check a `let` statement. + pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { + self.check_decl(local.into()); } pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { @@ -891,17 +912,18 @@ fn overwrite_local_ty_if_err( &self, - local: &'tcx hir::Local<'tcx>, + hir_id: hir::HirId, + pat: &'tcx hir::Pat<'tcx>, decl_ty: Ty<'tcx>, ty: Ty<'tcx>, ) { if ty.references_error() { // Override the types everywhere with `err()` to avoid knock on errors. - self.write_ty(local.hir_id, ty); - self.write_ty(local.pat.hir_id, ty); + self.write_ty(hir_id, ty); + self.write_ty(pat.hir_id, ty); let local_ty = LocalTy { decl_ty, revealed_ty: ty }; - self.locals.borrow_mut().insert(local.hir_id, local_ty); - self.locals.borrow_mut().insert(local.pat.hir_id, local_ty); + self.locals.borrow_mut().insert(hir_id, local_ty); + self.locals.borrow_mut().insert(pat.hir_id, local_ty); } } @@ -938,8 +960,8 @@ (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } - QPath::LangItem(lang_item, span) => { - self.resolve_lang_item_path(lang_item, span, hir_id) + QPath::LangItem(lang_item, span, id) => { + self.resolve_lang_item_path(lang_item, span, hir_id, id) } } } @@ -990,7 +1012,7 @@ } result_code } - let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(Lrc::new(error.obligation.cause.code.clone())) { + let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) { ObligationCauseCode::BuiltinDerivedObligation(code) | ObligationCauseCode::ImplDerivedObligation(code) | ObligationCauseCode::DerivedObligation(code) => { @@ -1033,18 +1055,18 @@ } // We make sure that only *one* argument matches the obligation failure // and we assign the obligation's span to its expression's. - error.obligation.cause.make_mut().span = args[ref_in].span; - let code = error.obligation.cause.code.clone(); - error.obligation.cause.make_mut().code = + error.obligation.cause.span = args[ref_in].span; + let parent_code = error.obligation.cause.clone_code(); + *error.obligation.cause.make_mut_code() = ObligationCauseCode::FunctionArgumentObligation { arg_hir_id: args[ref_in].hir_id, call_hir_id: expr.hir_id, - parent_code: Lrc::new(code), + parent_code, }; - } else if error.obligation.cause.make_mut().span == call_sp { + } else if error.obligation.cause.span == call_sp { // Make function calls point at the callee, not the whole thing. if let hir::ExprKind::Call(callee, _) = expr.kind { - error.obligation.cause.make_mut().span = callee.span; + error.obligation.cause.span = callee.span; } } } @@ -1085,7 +1107,7 @@ let ty = >::ast_ty_to_ty(self, hir_ty); let ty = self.resolve_vars_if_possible(ty); if ty == predicate.self_ty() { - error.obligation.cause.make_mut().span = hir_ty.span; + error.obligation.cause.span = hir_ty.span; } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs 2022-02-23 04:07:21.000000000 +0000 @@ -6,7 +6,6 @@ use crate::check::method::{self, MethodCallee, SelfSource}; use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; -use rustc_ast::TraitObjectSyntax; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported}; @@ -14,7 +13,7 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind}; +use rustc_hir::{ExprKind, GenericArg, Node, QPath}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; @@ -28,8 +27,6 @@ Ty, UserType, }; use rustc_session::lint; -use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; -use rustc_span::edition::Edition; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; @@ -304,20 +301,26 @@ // is a valid NeverToAny adjustment, because it can't // be reached. (&[Adjustment { kind: Adjust::NeverToAny, .. }], _) => return, - (&[ - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, - ], &[ - Adjustment { kind: Adjust::Deref(_), .. }, - .. // Any following adjustments are allowed. - ]) => { + ( + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, + ], + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + .., // Any following adjustments are allowed. + ], + ) => { // A reborrow has no effect before a dereference. } // FIXME: currently we never try to compose autoderefs // and ReifyFnPointer/UnsafeFnPointer, but we could. - _ => - bug!("while adjusting {:?}, can't compose {:?} and {:?}", - expr, entry.get(), adj) + _ => bug!( + "while adjusting {:?}, can't compose {:?} and {:?}", + expr, + entry.get(), + adj + ), }; *entry.get_mut() = adj; } @@ -495,6 +498,13 @@ ty } + pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> &'tcx ty::Const<'tcx> { + match length { + &hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span), + hir::ArrayLen::Body(anon_const) => self.to_const(anon_const), + } + } + pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> { let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id); let c = ty::Const::from_anon_const(self.tcx, const_def_id); @@ -610,10 +620,7 @@ #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - let errors = self - .fulfillment_cx - .borrow_mut() - .select_all_with_constness_or_error(&self, self.inh.constness); + let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); @@ -626,10 +633,7 @@ fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { - let mut result = self - .fulfillment_cx - .borrow_mut() - .select_with_constness_where_possible(self, self.inh.constness); + let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); @@ -791,6 +795,7 @@ lang_item: hir::LangItem, span: Span, hir_id: hir::HirId, + expr_hir_id: Option, ) -> (Res, Ty<'tcx>) { let def_id = self.tcx.require_lang_item(lang_item, Some(span)); let def_kind = self.tcx.def_kind(def_id); @@ -804,7 +809,23 @@ let ty = item_ty.subst(self.tcx, substs); self.write_resolution(hir_id, Ok((def_kind, def_id))); - self.add_required_obligations(span, def_id, &substs); + self.add_required_obligations_with_code( + span, + def_id, + &substs, + match lang_item { + hir::LangItem::IntoFutureIntoFuture => { + ObligationCauseCode::AwaitableExpr(expr_hir_id) + } + hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { + ObligationCauseCode::ForLoopIterator + } + hir::LangItem::TryTraitFromOutput + | hir::LangItem::TryTraitFromResidual + | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, + _ => traits::ItemObligation(def_id), + }, + ); (Res::Def(def_kind, def_id), ty) } @@ -838,7 +859,7 @@ // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - (>::ast_ty_to_ty(self, qself), qself, segment) + (>::ast_ty_to_ty_in_path(self, qself), qself, segment) } QPath::LangItem(..) => { bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") @@ -884,7 +905,6 @@ }); if result.is_ok() { - self.maybe_lint_bare_trait(qpath, hir_id, span); self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); } @@ -897,56 +917,6 @@ ) } - fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Span) { - if let QPath::TypeRelative(self_ty, _) = qpath { - if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let msg = "trait objects without an explicit `dyn` are deprecated"; - let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span) { - Ok(s) if poly_trait_ref.trait_ref.path.is_global() => { - (format!("dyn ({})", s), Applicability::MachineApplicable) - } - Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), - Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), - }; - // Wrap in `<..>` if it isn't already. - let sugg = match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(s) if s.starts_with('<') => sugg, - _ => format!("<{}>", sugg), - }; - let sugg_label = "use `dyn`"; - if self.sess().edition() >= Edition::Edition2021 { - let mut err = rustc_errors::struct_span_err!( - self.sess(), - self_ty.span, - E0782, - "{}", - msg, - ); - err.span_suggestion( - self_ty.span, - sugg_label, - sugg, - Applicability::MachineApplicable, - ) - .emit(); - } else { - self.tcx.struct_span_lint_hir( - BARE_TRAIT_OBJECTS, - hir_id, - self_ty.span, - |lint| { - let mut db = lint.build(msg); - db.span_suggestion(self_ty.span, sugg_label, sugg, app); - db.emit() - }, - ); - } - } - } - } - /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise. pub(in super::super) fn get_node_fn_decl( &self, @@ -1097,12 +1067,9 @@ (_, _) => return None, }; - let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id); - let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id); - match ( - &self.tcx.hir().expect_item(last_hir_id).kind, - &self.tcx.hir().expect_item(exp_hir_id).kind, + &self.tcx.hir().expect_item(last_local_id).kind, + &self.tcx.hir().expect_item(exp_local_id).kind, ) { ( hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), @@ -1433,7 +1400,7 @@ >::create_substs_for_generic_args( tcx, def_id, - &[][..], + &[], has_self, self_ty, &arg_count, @@ -1489,12 +1456,27 @@ } /// Add all the obligations that are required, substituting and normalized appropriately. - #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] crate fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { + self.add_required_obligations_with_code( + span, + def_id, + substs, + traits::ItemObligation(def_id), + ) + } + + #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] + fn add_required_obligations_with_code( + &self, + span: Span, + def_id: DefId, + substs: &SubstsRef<'tcx>, + code: ObligationCauseCode<'tcx>, + ) { let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); for obligation in traits::predicates_for_generics( - traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), + traits::ObligationCause::new(span, self.body_id, code), self.param_env, bounds, ) { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/gather_locals.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/gather_locals.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/gather_locals.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/gather_locals.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,6 +7,31 @@ use rustc_span::Span; use rustc_trait_selection::traits; +/// A declaration is an abstraction of [hir::Local] and [hir::Let]. +/// +/// It must have a hir_id, as this is how we connect gather_locals to the check functions. +pub(super) struct Declaration<'a> { + pub hir_id: hir::HirId, + pub pat: &'a hir::Pat<'a>, + pub ty: Option<&'a hir::Ty<'a>>, + pub span: Span, + pub init: Option<&'a hir::Expr<'a>>, +} + +impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> { + fn from(local: &'a hir::Local<'a>) -> Self { + let hir::Local { hir_id, pat, ty, span, init, .. } = *local; + Declaration { hir_id, pat, ty, span, init } + } +} + +impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> { + fn from(let_expr: &'a hir::Let<'a>) -> Self { + let hir::Let { hir_id, pat, ty, span, init } = *let_expr; + Declaration { hir_id, pat, ty, span, init: Some(init) } + } +} + pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, // parameters are special cases of patterns, but we want to handle them as @@ -41,18 +66,12 @@ } } } -} - -impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { - type Map = intravisit::ErasedMap<'tcx>; - - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::None - } - // Add explicitly-declared locals. - fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) { - let local_ty = match local.ty { + /// Allocates a [LocalTy] for a declaration, which may have a type annotation. If it does have + /// a type annotation, then the LocalTy stored will be the resolved type. This may be found + /// again during type checking by querying [FnCtxt::local_ty] for the same hir_id. + fn declare(&mut self, decl: Declaration<'tcx>) { + let local_ty = match decl.ty { Some(ref ty) => { let o_ty = self.fcx.to_ty(&ty); @@ -68,16 +87,34 @@ } None => None, }; - self.assign(local.span, local.hir_id, local_ty); + self.assign(decl.span, decl.hir_id, local_ty); debug!( "local variable {:?} is assigned type {}", - local.pat, - self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&local.hir_id).unwrap().decl_ty) + decl.pat, + self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&decl.hir_id).unwrap().decl_ty) ); + } +} + +impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { + type Map = intravisit::ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + // Add explicitly-declared locals. + fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) { + self.declare(local.into()); intravisit::walk_local(self, local); } + fn visit_let_expr(&mut self, let_expr: &'tcx hir::Let<'tcx>) { + self.declare(let_expr.into()); + intravisit::walk_let_expr(self, let_expr); + } + fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span); intravisit::walk_param(self, param); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/generator_interior.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/generator_interior.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/generator_interior.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/generator_interior.rs 2022-02-23 04:07:21.000000000 +0000 @@ -536,22 +536,28 @@ } has_emitted } - ty::Tuple(ref tys) => { + ty::Tuple(_) => { let mut has_emitted = false; - let spans = if let Some(hir::ExprKind::Tup(comps)) = data.expr.map(|e| &e.kind) { - debug_assert_eq!(comps.len(), tys.len()); - comps.iter().map(|e| e.span).collect() - } else { - vec![] + let comps = match data.expr.map(|e| &e.kind) { + Some(hir::ExprKind::Tup(comps)) => { + debug_assert_eq!(comps.len(), ty.tuple_fields().count()); + Some(comps) + } + _ => None, }; - for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + for (i, ty) in ty.tuple_fields().enumerate() { let descr_post = &format!(" in tuple element {}", i); - let span = *spans.get(i).unwrap_or(&data.source_span); + let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span); if check_must_not_suspend_ty( fcx, ty, hir_id, - SuspendCheckData { descr_post, source_span: span, ..data }, + SuspendCheckData { + descr_post, + expr: comps.and_then(|comps| comps.get(i)), + source_span: span, + ..data + }, ) { has_emitted = true; } @@ -603,7 +609,7 @@ // Add optional reason note if let Some(note) = attr.value_str() { // FIXME(guswynn): consider formatting this better - err.span_note(data.source_span, ¬e.as_str()); + err.span_note(data.source_span, note.as_str()); } // Add some quick suggestions on what to do diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/inherited.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/inherited.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/inherited.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/inherited.rs 2022-02-23 04:07:21.000000000 +0000 @@ -53,9 +53,6 @@ pub(super) deferred_generator_interiors: RefCell, hir::GeneratorKind)>>, - /// Reports whether this is in a const context. - pub(super) constness: hir::Constness, - pub(super) body_id: Option, /// Whenever we introduce an adjustment from `!` into a type variable, @@ -79,7 +76,7 @@ def_id: LocalDefId, } -impl Inherited<'_, 'tcx> { +impl<'tcx> Inherited<'_, 'tcx> { pub fn build(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> InheritedBuilder<'tcx> { let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; @@ -100,20 +97,10 @@ } } -impl Inherited<'a, 'tcx> { +impl<'a, 'tcx> Inherited<'a, 'tcx> { pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self { let tcx = infcx.tcx; let item_id = tcx.hir().local_def_id_to_hir_id(def_id); - Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck()) - } - - pub(super) fn with_constness( - infcx: InferCtxt<'a, 'tcx>, - def_id: LocalDefId, - constness: hir::Constness, - ) -> Self { - let tcx = infcx.tcx; - let item_id = tcx.hir().local_def_id_to_hir_id(def_id); let body_id = tcx.hir().maybe_body_owned_by(item_id); Inherited { @@ -128,7 +115,6 @@ deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), diverging_type_vars: RefCell::new(Default::default()), - constness, body_id, } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/_match.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/_match.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/_match.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/_match.rs 2022-02-23 04:07:21.000000000 +0000 @@ -557,7 +557,7 @@ } } -fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option { +fn arms_contain_ref_bindings<'tcx>(arms: &'tcx [hir::Arm<'tcx>]) -> Option { arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m { hir::Mutability::Mut => 1, hir::Mutability::Not => 0, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -7,7 +7,7 @@ pub mod probe; mod suggest; -pub use self::suggest::{SelfSource, TraitInfo}; +pub use self::suggest::SelfSource; pub use self::CandidateSource::*; pub use self::MethodError::*; @@ -22,7 +22,7 @@ use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; @@ -31,7 +31,6 @@ use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { - suggest::provide(providers); probe::provide(providers); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/prelude2021.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/prelude2021.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/prelude2021.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/prelude2021.rs 2022-02-23 04:07:21.000000000 +0000 @@ -345,10 +345,7 @@ let import_items: Vec<_> = applicable_trait .import_ids .iter() - .map(|&import_id| { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id); - self.tcx.hir().expect_item(hir_id) - }) + .map(|&import_id| self.tcx.hir().expect_item(import_id)) .collect(); // Find an identifier with which this trait was imported (note that `_` doesn't count). diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/probe.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/probe.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/probe.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/probe.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{find_best_match_for_name, lev_distance}; @@ -1038,7 +1038,7 @@ .collect(); // Sort them by the name so we have a stable result. - names.sort_by_cached_key(|n| n.as_str()); + names.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap()); names } @@ -1372,7 +1372,7 @@ if applicable_candidates.len() > 1 { if let Some(pick) = - self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates[..]) + self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates) { return Some(Ok(pick)); } @@ -1908,7 +1908,7 @@ .associated_items(def_id) .in_definition_order() .filter(|x| { - let dist = lev_distance(&*name.as_str(), &x.ident.as_str()); + let dist = lev_distance(name.as_str(), x.ident.as_str()); x.kind.namespace() == Namespace::ValueNS && dist > 0 && dist <= max_dist }) .copied() diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/suggest.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/suggest.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/suggest.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/method/suggest.rs 2022-02-23 04:07:21.000000000 +0000 @@ -5,14 +5,14 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def::Namespace; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::fast_reject::simplify_type; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol}; @@ -67,6 +67,10 @@ } } + fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { + self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) + } + pub fn report_method_error( &self, mut span: Span, @@ -691,7 +695,23 @@ let mut restrict_type_params = false; let mut unsatisfied_bounds = false; - if !unsatisfied_predicates.is_empty() { + if item_name.name == sym::count && self.is_slice_ty(actual, span) { + let msg = "consider using `len` instead"; + if let SelfSource::MethodCall(_expr) = source { + err.span_suggestion_short( + span, + msg, + String::from("len"), + Applicability::MachineApplicable, + ); + } else { + err.span_label(span, msg); + } + if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { + let iterator_trait = self.tcx.def_path_str(iterator_trait); + err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement")); + } + } else if !unsatisfied_predicates.is_empty() { let def_span = |def_id| { self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) }; @@ -812,7 +832,7 @@ for (data, p, parent_p) in unsatisfied_predicates .iter() .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) - .filter_map(|(p, parent, c)| match c.code { + .filter_map(|(p, parent, c)| match c.code() { ObligationCauseCode::ImplDerivedObligation(ref data) => { Some((data, p, parent)) } @@ -990,9 +1010,9 @@ } } - let mut fallback_span = true; - let msg = "remove this method call"; if item_name.name == sym::as_str && actual.peel_refs().is_str() { + let msg = "remove this method call"; + let mut fallback_span = true; if let SelfSource::MethodCall(expr) = source { let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); @@ -1175,11 +1195,11 @@ fn suggest_derive( &self, err: &mut DiagnosticBuilder<'_>, - unsatisfied_predicates: &Vec<( + unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option>, Option>, - )>, + )], ) { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::::new(); @@ -1216,23 +1236,24 @@ traits.push(self.tcx.def_span(trait_pred.def_id())); } } - derives.sort(); - let derives_grouped = derives.into_iter().fold( - Vec::<(String, Span, String)>::new(), - |mut acc, (self_name, self_span, trait_name)| { - if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() { - if acc_self_name == &self_name { - traits.push_str(format!(", {}", trait_name).as_str()); - return acc; - } - } - acc.push((self_name, self_span, trait_name)); - acc - }, - ); traits.sort(); traits.dedup(); + derives.sort(); + derives.dedup(); + + let mut derives_grouped = Vec::<(String, Span, String)>::new(); + for (self_name, self_span, trait_name) in derives.into_iter() { + if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut() + { + if last_self_name == &self_name { + last_trait_names.push_str(format!(", {}", trait_name).as_str()); + continue; + } + } + derives_grouped.push((self_name, self_span, trait_name)); + } + let len = traits.len(); if len > 0 { let span: MultiSpan = traits.into(); @@ -1290,25 +1311,66 @@ mut msg: String, candidates: Vec, ) { + let parent_map = self.tcx.visible_parent_map(()); + + // Separate out candidates that must be imported with a glob, because they are named `_` + // and cannot be referred with their identifier. + let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| { + if let Some(parent_did) = parent_map.get(trait_did) { + // If the item is re-exported as `_`, we should suggest a glob-import instead. + if Some(*parent_did) != self.tcx.parent(*trait_did) + && self + .tcx + .item_children(*parent_did) + .iter() + .filter(|child| child.res.opt_def_id() == Some(*trait_did)) + .all(|child| child.ident.name == kw::Underscore) + { + return false; + } + } + + true + }); + let module_did = self.tcx.parent_module(self.body_id); let (span, found_use) = find_use_placement(self.tcx, module_did); if let Some(span) = span { - let path_strings = candidates.iter().map(|did| { + let path_strings = candidates.iter().map(|trait_did| { // Produce an additional newline to separate the new use statement // from the directly following item. let additional_newline = if found_use { "" } else { "\n" }; format!( "use {};\n{}", - with_crate_prefix(|| self.tcx.def_path_str(*did)), + with_crate_prefix(|| self.tcx.def_path_str(*trait_did)), additional_newline ) }); - err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect); + let glob_path_strings = globs.iter().map(|trait_did| { + let parent_did = parent_map.get(trait_did).unwrap(); + + // Produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { "" } else { "\n" }; + format!( + "use {}::*; // trait {}\n{}", + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + additional_newline + ) + }); + + err.span_suggestions( + span, + &msg, + path_strings.chain(glob_path_strings), + Applicability::MaybeIncorrect, + ); } else { - let limit = if candidates.len() == 5 { 5 } else { 4 }; + let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 }; for (i, trait_did) in candidates.iter().take(limit).enumerate() { - if candidates.len() > 1 { + if candidates.len() + globs.len() > 1 { msg.push_str(&format!( "\ncandidate #{}: `use {};`", i + 1, @@ -1321,10 +1383,30 @@ )); } } + for (i, trait_did) in + globs.iter().take(limit.saturating_sub(candidates.len())).enumerate() + { + let parent_did = parent_map.get(trait_did).unwrap(); + + if candidates.len() + globs.len() > 1 { + msg.push_str(&format!( + "\ncandidate #{}: `use {}::*; // trait {}`", + candidates.len() + i + 1, + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + )); + } else { + msg.push_str(&format!( + "\n`use {}::*; // trait {}`", + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + )); + } + } if candidates.len() > limit { - msg.push_str(&format!("\nand {} others", candidates.len() - limit)); + msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit)); } - err.note(&msg[..]); + err.note(&msg); } } @@ -1683,7 +1765,9 @@ // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) { + } else if let Some(simp_rcvr_ty) = + simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes, StripReferences::No) + { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -1696,7 +1780,12 @@ }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap(); - let imp_simp = simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::No, + ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { @@ -1833,76 +1922,10 @@ } } -/// Retrieves all traits in this crate and any dependent crates. +/// Retrieves all traits in this crate and any dependent crates, +/// and wraps them into `TraitInfo` for custom sorting. pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { - tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect() -} - -/// Computes all traits in this crate and any dependent crates. -fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { - use hir::itemlikevisit; - - let mut traits = vec![]; - - // Crate-local: - - struct Visitor<'a> { - traits: &'a mut Vec, - } - - impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> { - fn visit_item(&mut self, i: &'v hir::Item<'v>) { - match i.kind { - hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.traits.push(i.def_id.to_def_id()); - } - _ => (), - } - } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} - } - - tcx.hir().visit_all_item_likes(&mut Visitor { traits: &mut traits }); - - // Cross-crate: - - let mut external_mods = FxHashSet::default(); - fn handle_external_res( - tcx: TyCtxt<'_>, - traits: &mut Vec, - external_mods: &mut FxHashSet, - res: Res, - ) { - match res { - Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => { - traits.push(def_id); - } - Res::Def(DefKind::Mod, def_id) => { - if !external_mods.insert(def_id) { - return; - } - for child in tcx.item_children(def_id).iter() { - handle_external_res(tcx, traits, external_mods, child.res) - } - } - _ => {} - } - } - for &cnum in tcx.crates(()).iter() { - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id)); - } - - tcx.arena.alloc_from_iter(traits) -} - -pub fn provide(providers: &mut ty::query::Providers) { - providers.all_traits = compute_all_traits; + tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { @@ -1948,7 +1971,7 @@ (span, found_use) } -fn print_disambiguation_help( +fn print_disambiguation_help<'tcx>( item_name: Ident, args: Option<&'tcx [hir::Expr<'tcx>]>, err: &mut DiagnosticBuilder<'_>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/mod.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/mod.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/mod.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/mod.rs 2022-02-23 04:07:21.000000000 +0000 @@ -508,7 +508,7 @@ /// Given a `DefId` for an opaque type in return position, find its parent item's return /// expressions. -fn get_owner_return_paths( +fn get_owner_return_paths<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> { @@ -686,9 +686,8 @@ }; let mut where_clauses = vec![]; for (ty, bounds) in types { - for bound in &bounds { - where_clauses.push(format!("{}: {}", ty, tcx.def_path_str(*bound))); - } + where_clauses + .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound)))); } for projection in &projections { let p = projection.skip_binder(); @@ -907,7 +906,7 @@ tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { check_item_type(self.tcx, i); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/op.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/op.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/op.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/op.rs 2022-02-23 04:07:21.000000000 +0000 @@ -492,7 +492,6 @@ ) -> bool /* did we suggest to call a function because of missing parentheses? */ { err.span_label(span, ty.to_string()); if let FnDef(def_id, _) = *ty.kind() { - let source_map = self.tcx.sess.source_map(); if !self.tcx.has_typeck_results(def_id) { return false; } @@ -517,20 +516,18 @@ .lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign)) .is_ok() { - if let Ok(snippet) = source_map.span_to_snippet(span) { - let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { - (format!("{}( /* arguments */ )", snippet), Applicability::HasPlaceholders) - } else { - (format!("{}()", snippet), Applicability::MaybeIncorrect) - }; + let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { + ("( /* arguments */ )".to_string(), Applicability::HasPlaceholders) + } else { + ("()".to_string(), Applicability::MaybeIncorrect) + }; - err.span_suggestion( - span, - "you might have forgotten to call this function", - variable_snippet, - applicability, - ); - } + err.span_suggestion_verbose( + span.shrink_to_hi(), + "you might have forgotten to call this function", + variable_snippet, + applicability, + ); return true; } } @@ -896,7 +893,7 @@ } /// Dereferences a single level of immutable referencing. -fn deref_ty_if_possible(ty: Ty<'tcx>) -> Ty<'tcx> { +fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { match ty.kind() { ty::Ref(_, ty, hir::Mutability::Not) => ty, _ => ty, @@ -1010,7 +1007,7 @@ struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span); -impl TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.0.tcx } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/pat.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/pat.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/pat.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/pat.rs 2022-02-23 04:07:21.000000000 +0000 @@ -740,7 +740,7 @@ } } - fn check_pat_path( + fn check_pat_path<'b>( &self, pat: &Pat<'_>, path_resolution: (Res, Option>, &'b [hir::PathSegment<'b>]), @@ -816,7 +816,7 @@ false } - fn emit_bad_pat_path( + fn emit_bad_pat_path<'b>( &self, mut e: DiagnosticBuilder<'_>, pat_span: Span, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/place_op.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/place_op.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/place_op.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/place_op.rs 2022-02-23 04:07:21.000000000 +0000 @@ -440,8 +440,11 @@ } // If we have an autoref followed by unsizing at the end, fix the unsize target. - if let [.., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }] = - adjustments[..] + if let [ + .., + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, + Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }, + ] = adjustments[..] { *target = method.sig.inputs()[0]; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/regionck.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/regionck.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/regionck.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/regionck.rs 2022-02-23 04:07:21.000000000 +0000 @@ -106,7 +106,7 @@ pub(crate) trait OutlivesEnvironmentExt<'tcx> { fn add_implied_bounds( &mut self, - infcx: &InferCtxt<'a, 'tcx>, + infcx: &InferCtxt<'_, 'tcx>, fn_sig_tys: FxHashSet>, body_id: hir::HirId, span: Span, @@ -130,7 +130,7 @@ /// add those assumptions into the outlives-environment. /// /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs` - fn add_implied_bounds( + fn add_implied_bounds<'a>( &mut self, infcx: &InferCtxt<'a, 'tcx>, fn_sig_tys: FxHashSet>, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/upvar.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/upvar.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/upvar.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/upvar.rs 2022-02-23 04:07:21.000000000 +0000 @@ -687,15 +687,11 @@ r ), ( - l - @ - (ProjectionKind::Index + l @ (ProjectionKind::Index | ProjectionKind::Subslice | ProjectionKind::Deref | ProjectionKind::Field(..)), - r - @ - (ProjectionKind::Index + r @ (ProjectionKind::Index | ProjectionKind::Subslice | ProjectionKind::Deref | ProjectionKind::Field(..)), @@ -908,10 +904,7 @@ ) -> MigrationWarningReason { let mut reasons = MigrationWarningReason::default(); - for auto_trait in auto_trait_reasons { - reasons.auto_traits.push(auto_trait); - } - + reasons.auto_traits.extend(auto_trait_reasons); reasons.drop_order = drop_order; reasons @@ -1679,7 +1672,7 @@ } /// Returns a Ty that applies the specified capture kind on the provided capture Ty -fn apply_capture_kind_on_capture_ty( +fn apply_capture_kind_on_capture_ty<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, capture_kind: UpvarCapture<'tcx>, @@ -1692,7 +1685,7 @@ } /// Returns the Span of where the value with the provided HirId would be dropped -fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span { +fn drop_location_span<'tcx>(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span { let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap(); let owner_node = tcx.hir().get(owner_id); @@ -2006,7 +1999,7 @@ /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture /// them completely. /// - No projections are applied on top of Union ADTs, since these require unsafe blocks. -fn restrict_precision_for_unsafe( +fn restrict_precision_for_unsafe<'tcx>( mut place: Place<'tcx>, mut curr_mode: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { @@ -2104,7 +2097,7 @@ (place, kind) } -fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { +fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let variable_name = match place.base { PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), @@ -2127,7 +2120,7 @@ format!("{}[{}]", variable_name, projections_str) } -fn construct_capture_kind_reason_string( +fn construct_capture_kind_reason_string<'tcx>( tcx: TyCtxt<'_>, place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, @@ -2142,13 +2135,13 @@ format!("{} captured as {} here", place_str, capture_kind_str) } -fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { +fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let place_str = construct_place_string(tcx, place); format!("{} used here", place_str) } -fn construct_capture_info_string( +fn construct_capture_info_string<'tcx>( tcx: TyCtxt<'_>, place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, @@ -2240,7 +2233,7 @@ /// would've already handled `E1`, and have an existing capture_information for it. /// Calling `determine_capture_info(existing_info_e1, current_info_e2)` will return /// `existing_info_e1` in this case, allowing us to point to `E1` in case of diagnostics. -fn determine_capture_info( +fn determine_capture_info<'tcx>( capture_info_a: ty::CaptureInfo<'tcx>, capture_info_b: ty::CaptureInfo<'tcx>, ) -> ty::CaptureInfo<'tcx> { @@ -2299,7 +2292,7 @@ /// /// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place` /// contained `Deref` of `&mut`. -fn truncate_place_to_len_and_update_capture_kind( +fn truncate_place_to_len_and_update_capture_kind<'tcx>( place: &mut Place<'tcx>, curr_mode: &mut ty::UpvarCapture<'tcx>, len: usize, @@ -2337,7 +2330,7 @@ /// `PlaceAncestryRelation::Ancestor` implies Place A is ancestor of Place B /// `PlaceAncestryRelation::Descendant` implies Place A is descendant of Place B /// `PlaceAncestryRelation::Divergent` implies neither of them is the ancestor of the other. -fn determine_place_ancestry_relation( +fn determine_place_ancestry_relation<'tcx>( place_a: &Place<'tcx>, place_b: &Place<'tcx>, ) -> PlaceAncestryRelation { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/wfcheck.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/wfcheck.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/wfcheck.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check/wfcheck.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,6 @@ use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, - WithConstness, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -84,8 +83,7 @@ /// the types first. #[instrument(skip(tcx), level = "debug")] pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id); debug!( ?item.def_id, @@ -197,7 +195,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_item = tcx.hir().expect_trait_item(hir_id); + let trait_item = tcx.hir().expect_trait_item(def_id); let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -207,8 +205,8 @@ check_object_unsafe_self_trait_by_name(tcx, trait_item); check_associated_item(tcx, trait_item.def_id, span, method_sig); - let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id); - let encl_trait = tcx.hir().expect_item(encl_trait_hir_id); + let encl_trait_def_id = tcx.hir().get_parent_did(hir_id); + let encl_trait = tcx.hir().expect_item(encl_trait_def_id); let encl_trait_def_id = encl_trait.def_id.to_def_id(); let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { Some("fn") @@ -428,22 +426,48 @@ } } - // If there are any missing clauses, emit an error - let mut clauses = clauses.unwrap_or_default(); + // If there are any clauses that aren't provable, emit an error + let clauses = clauses.unwrap_or_default(); debug!(?clauses); if !clauses.is_empty() { - let written_predicates: ty::GenericPredicates<'_> = - tcx.explicit_predicates_of(trait_item.def_id); + let param_env = tcx.param_env(trait_item.def_id); + let mut clauses: Vec<_> = clauses - .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause)) + .into_iter() + .filter(|clause| match clause.kind().skip_binder() { + ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { + !region_known_to_outlive( + tcx, + trait_item.hir_id(), + param_env, + &FxHashSet::default(), + a, + b, + ) + } + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { + !ty_known_to_outlive( + tcx, + trait_item.hir_id(), + param_env, + &FxHashSet::default(), + a, + b, + ) + } + _ => bug!("Unexpected PredicateKind"), + }) .map(|clause| format!("{}", clause)) .collect(); + // We sort so that order is predictable clauses.sort(); + if !clauses.is_empty() { + let plural = if clauses.len() > 1 { "s" } else { "" }; let mut err = tcx.sess.struct_span_err( trait_item.span, - &format!("Missing required bounds on {}", trait_item.ident), + &format!("missing required bound{} on `{}`", plural, trait_item.ident), ); let suggestion = format!( @@ -457,11 +481,22 @@ ); err.span_suggestion( trait_item.generics.where_clause.tail_span_for_suggestion(), - "add the required where clauses", + &format!("add the required where clause{}", plural), suggestion, Applicability::MachineApplicable, ); + let bound = if clauses.len() > 1 { "these bounds are" } else { "this bound is" }; + err.note(&format!( + "{} currently required to ensure that impls have maximum flexibility", + bound + )); + err.note( + "we are soliciting feedback, see issue #87479 \ + \ + for more information", + ); + err.emit() } } @@ -543,7 +578,8 @@ }); use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; - (&infcx).push_sub_region_constraint(origin, region_a, region_b); + // `region_a: region_b` -> `region_b <= region_a` + (&infcx).push_sub_region_constraint(origin, region_b, region_a); let errors = infcx.resolve_regions( id.expect_owner().to_def_id(), @@ -680,12 +716,12 @@ } pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let impl_item = tcx.hir().expect_impl_item(hir_id); + let impl_item = tcx.hir().expect_impl_item(def_id); let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), - hir::ImplItemKind::TyAlias(ty) => (None, ty.span), + // Constrain binding and overflow error spans to `` in `type foo = `. + hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span), _ => (None, impl_item.span), }; @@ -698,7 +734,6 @@ hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (), // Const parameters are well formed if their type is structural match. - // FIXME(const_generics_defaults): we also need to check that the `default` is wf. hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id)); @@ -1060,6 +1095,20 @@ ); } + // Ensure that the end result is `Sync` in a non-thread local `static`. + let should_check_for_sync = tcx.static_mutability(item_id.to_def_id()) + == Some(hir::Mutability::Not) + && !tcx.is_foreign_item(item_id.to_def_id()) + && !tcx.is_thread_local_static(item_id.to_def_id()); + + if should_check_for_sync { + fcx.register_bound( + item_ty, + tcx.require_lang_item(LangItem::Sync, Some(ty_span)), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::SharedStatic), + ); + } + // No implied bounds in a const, etc. FxHashSet::default() }); @@ -1439,7 +1488,7 @@ } } -fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { +fn e0307<'tcx>(fcx: &FnCtxt<'_, 'tcx>, span: Span, receiver_ty: Ty<'_>) { struct_span_err!( fcx.tcx.sess.diagnostic(), span, @@ -1542,7 +1591,7 @@ true } -fn receiver_is_implemented( +fn receiver_is_implemented<'tcx>( fcx: &FnCtxt<'_, 'tcx>, receiver_trait_def_id: DefId, cause: ObligationCause<'tcx>, @@ -1685,13 +1734,13 @@ tcx: TyCtxt<'tcx>, } -impl CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> CheckTypeWellFormedVisitor<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> CheckTypeWellFormedVisitor<'tcx> { CheckTypeWellFormedVisitor { tcx } } } -impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { fn visit_item(&self, i: &'tcx hir::Item<'tcx>) { Visitor::visit_item(&mut self.clone(), i); } @@ -1709,7 +1758,7 @@ } } -impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { type Map = hir_map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { @@ -1810,7 +1859,7 @@ // Inherent impl: take implied bounds from the `self` type. let self_ty = self.tcx.type_of(impl_def_id); let self_ty = self.normalize_associated_types_in(span, self_ty); - std::array::IntoIter::new([self_ty]).collect() + FxHashSet::from_iter([self_ty]) } } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check_unused.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check_unused.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check_unused.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/check_unused.rs 2022-02-23 04:07:21.000000000 +0000 @@ -21,7 +21,7 @@ unused_crates_lint(tcx); } -impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'_> for CheckVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { if item.vis.node.is_pub() || item.span.is_dummy() { return; @@ -43,7 +43,7 @@ used_trait_imports: FxHashSet, } -impl CheckVisitor<'tcx> { +impl<'tcx> CheckVisitor<'tcx> { fn check_import(&self, item_id: hir::ItemId, span: Span) { if !self.tcx.maybe_unused_trait_import(item_id.def_id) { return; @@ -119,13 +119,13 @@ for extern_crate in &crates_to_lint { let def_id = extern_crate.def_id.expect_local(); - let id = tcx.hir().local_def_id_to_hir_id(def_id); - let item = tcx.hir().expect_item(id); + let item = tcx.hir().expect_item(def_id); // If the crate is fully unused, we suggest removing it altogether. // We do this in any edition. if extern_crate.warn_if_unused { if let Some(&span) = unused_extern_crates.get(&def_id) { + let id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.struct_span_lint_hir(lint, id, span, |lint| { // Removal suggestion span needs to include attributes (Issue #54400) let span_with_attrs = tcx @@ -173,6 +173,7 @@ if !tcx.get_attrs(extern_crate.def_id).is_empty() { continue; } + let id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { // Otherwise, we can convert it into a `use` of some kind. let base_replacement = match extern_crate.orig_name { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/builtin.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/builtin.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/builtin.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/builtin.rs 2022-02-23 04:07:21.000000000 +0000 @@ -52,8 +52,7 @@ return; } - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); - let sp = match tcx.hir().expect_item(impl_hir_id).kind { + let sp = match tcx.hir().expect_item(impl_did).kind { ItemKind::Impl(ref impl_) => impl_.self_ty.span, _ => bug!("expected Drop impl item"), }; @@ -78,7 +77,7 @@ match can_type_implement_copy(tcx, param_env, self_type) { Ok(()) => {} Err(CopyImplementationError::InfrigingFields(fields)) => { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind { tr.path.span } else { @@ -97,7 +96,7 @@ err.emit() } Err(CopyImplementationError::NotAnAdt) => { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span }; @@ -109,7 +108,7 @@ } } -fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { +fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); // Just compute this for the side-effects, in particular reporting @@ -119,7 +118,7 @@ tcx.at(span).coerce_unsized_info(impl_did); } -fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) { +fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); @@ -288,12 +287,12 @@ }) } -pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { +pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); // this provider should only get invoked for local def-ids - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local()); - let span = tcx.hir().span(impl_hir_id); + let impl_did = impl_did.expect_local(); + let span = tcx.def_span(impl_did); let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); @@ -315,6 +314,7 @@ debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target); tcx.infer_ctxt().enter(|infcx| { + let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); let cause = ObligationCause::misc(span, impl_hir_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, @@ -452,13 +452,13 @@ .emit(); return err_info; } else if diff_fields.len() > 1 { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) = item.kind { t.path.span } else { - tcx.hir().span(impl_hir_id) + tcx.def_span(impl_did) }; struct_span_err!( @@ -530,7 +530,11 @@ // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default()); + infcx.resolve_regions_and_report_errors( + impl_did.to_def_id(), + &outlives_env, + RegionckMode::default(), + ); CoerceUnsizedInfo { custom_kind: kind } }) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs 2022-02-23 04:07:21.000000000 +0000 @@ -18,7 +18,7 @@ tcx: TyCtxt<'tcx>, } -impl InherentOverlapChecker<'tcx> { +impl<'tcx> InherentOverlapChecker<'tcx> { /// Checks whether any associated items in impls 1 and 2 share the same identifier and /// namespace. fn impls_have_common_items( @@ -115,8 +115,8 @@ } } -impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { - fn visit_item(&mut self, item: &'v hir::Item<'v>) { +impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> { + fn visit_item(&mut self, item: &hir::Item<'_>) { match item.kind { hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) @@ -300,9 +300,9 @@ } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {} + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {} + fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/inherent_impls.rs 2022-02-23 04:07:21.000000000 +0000 @@ -38,7 +38,7 @@ impls_map: CrateInherentImpls, } -impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { +impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { let (ty, assoc_items) = match item.kind { hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => { @@ -370,7 +370,7 @@ fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} } -impl InherentCollect<'tcx> { +impl<'tcx> InherentCollect<'tcx> { fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) { if let Some(def_id) = def_id.as_local() { // Add the implementation to the mapping from implementation to base diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/orphan.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/orphan.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/orphan.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/orphan.rs 2022-02-23 04:07:21.000000000 +0000 @@ -143,7 +143,7 @@ Ok(()) } -fn emit_orphan_check_error( +fn emit_orphan_check_error<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, trait_span: Span, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/unsafety.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/unsafety.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/unsafety.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/coherence/unsafety.rs 2022-02-23 04:07:21.000000000 +0000 @@ -16,10 +16,10 @@ tcx: TyCtxt<'tcx>, } -impl UnsafetyChecker<'tcx> { +impl<'tcx> UnsafetyChecker<'tcx> { fn check_unsafety_coherence( &mut self, - item: &'v hir::Item<'v>, + item: &hir::Item<'_>, impl_generics: Option<&hir::Generics<'_>>, unsafety: hir::Unsafety, polarity: hir::ImplPolarity, @@ -83,8 +83,8 @@ } } -impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> { - fn visit_item(&mut self, item: &'v hir::Item<'v>) { +impl<'tcx> ItemLikeVisitor<'_> for UnsafetyChecker<'tcx> { + fn visit_item(&mut self, item: &hir::Item<'_>) { if let hir::ItemKind::Impl(ref impl_) = item.kind { self.check_unsafety_coherence( item, diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect/type_of.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect/type_of.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect/type_of.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect/type_of.rs 2022-02-23 04:07:21.000000000 +0000 @@ -13,7 +13,7 @@ use rustc_span::{Span, DUMMY_SP}; use super::ItemCtxt; -use super::{bad_placeholder_type, is_suggestable_infer_ty}; +use super::{bad_placeholder, is_suggestable_infer_ty}; /// Computes the relevant generic parameter for a potential generic const argument. /// @@ -172,7 +172,7 @@ // We've encountered an `AnonConst` in some path, so we need to // figure out which generic parameter it corresponds to and return // the relevant type. - let (arg_index, segment) = path + let filtered = path .segments .iter() .filter_map(|seg| seg.args.map(|args| (args.args, seg))) @@ -181,10 +181,17 @@ .filter(|arg| arg.is_const()) .position(|arg| arg.id() == hir_id) .map(|index| (index, seg)) - }) - .unwrap_or_else(|| { - bug!("no arg matching AnonConst in path"); }); + let (arg_index, segment) = match filtered { + None => { + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + "no arg matching AnonConst in path", + ); + return None; + } + Some(inner) => inner, + }; // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. @@ -387,13 +394,13 @@ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) + .mir_borrowck(owner) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() @@ -406,7 +413,7 @@ ), ); if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors + tcx.typeck(owner).tainted_by_errors { // Some error in the // owner fn prevented us from populating @@ -463,14 +470,7 @@ Node::Field(field) => icx.to_ty(field.ty), - Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); - if let Some(movability) = gen { - tcx.mk_generator(def_id.to_def_id(), substs, movability) - } else { - tcx.mk_closure(def_id.to_def_id(), substs) - } - } + Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id), Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => { // We defer to `type_of` of the corresponding parameter @@ -483,7 +483,7 @@ match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id == hir_id => + if constant.hir_id() == hir_id => { tcx.types.usize } @@ -724,7 +724,7 @@ } } - impl TypeFolder<'tcx> for MakeNameable<'tcx> { + impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -781,7 +781,7 @@ err.emit(); } None => { - let mut diag = bad_placeholder_type(tcx, vec![span], kind); + let mut diag = bad_placeholder(tcx, "type", vec![span], kind); if !ty.references_error() { let mut mk_nameable = MakeNameable::new(tcx); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/collect.rs 2022-02-23 04:07:21.000000000 +0000 @@ -41,7 +41,7 @@ use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt}; -use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; +use rustc_middle::ty::{ReprOptions, ToPredicate, TypeFoldable}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -147,7 +147,7 @@ /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed /// and suggest adding type parameters in the appropriate place, taking into consideration any and /// all already existing generic type parameters to avoid suggesting a name that is already in use. -crate fn placeholder_type_error( +crate fn placeholder_type_error<'tcx>( tcx: TyCtxt<'tcx>, span: Option, generics: &[hir::GenericParam<'_>], @@ -177,14 +177,12 @@ sugg.push((arg.span, (*type_name).to_string())); } else { let last = generics.iter().last().unwrap(); - sugg.push(( - // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. - last.bounds_span().unwrap_or(last.span).shrink_to_hi(), - format!(", {}", type_name), - )); + // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. + let span = last.bounds_span_for_suggestions().unwrap_or(last.span.shrink_to_hi()); + sugg.push((span, format!(", {}", type_name))); } - let mut err = bad_placeholder_type(tcx, placeholder_types, kind); + let mut err = bad_placeholder(tcx, "type", placeholder_types, kind); // Suggest, but only if it is not a function in const or static if suggest { @@ -225,7 +223,10 @@ err.emit(); } -fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { +fn reject_placeholder_type_signatures_in_item<'tcx>( + tcx: TyCtxt<'tcx>, + item: &'tcx hir::Item<'tcx>, +) { let (generics, suggest) = match &item.kind { hir::ItemKind::Union(_, generics) | hir::ItemKind::Enum(_, generics) @@ -253,7 +254,7 @@ ); } -impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -294,7 +295,9 @@ if let hir::ExprKind::Closure(..) = expr.kind { let def_id = self.tcx.hir().local_def_id(expr.hir_id); self.tcx.ensure().generics_of(def_id); - self.tcx.ensure().type_of(def_id); + // We do not call `type_of` for closures here as that + // depends on typecheck and would therefore hide + // any further errors in case one typeck fails. } intravisit::walk_expr(self, expr); } @@ -313,8 +316,9 @@ /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. -fn bad_placeholder_type( +fn bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, + placeholder_kind: &'static str, mut spans: Vec, kind: &'static str, ) -> rustc_errors::DiagnosticBuilder<'tcx> { @@ -325,7 +329,8 @@ tcx.sess, spans.clone(), E0121, - "the type placeholder `_` is not allowed within types on item signatures for {}", + "the {} placeholder `_` is not allowed within types on item signatures for {}", + placeholder_kind, kind ); for span in spans { @@ -334,7 +339,7 @@ err } -impl ItemCtxt<'tcx> { +impl<'tcx> ItemCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id } } @@ -352,7 +357,7 @@ } } -impl AstConv<'tcx> for ItemCtxt<'tcx> { +impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -392,7 +397,7 @@ _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder_type(self.tcx(), vec![span], "generic").emit(); + bad_placeholder(self.tcx(), "const", vec![span], "generic").emit(); // Typeck doesn't expect erased regions to be returned from `type_of`. let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { ty::ReErased => self.tcx.lifetimes.re_static, @@ -431,7 +436,7 @@ match self.node() { hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { let item = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id())); + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(self.hir_id())); match &item.kind { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) @@ -596,7 +601,11 @@ ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(hir::Impl { ref generics, .. }) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, @@ -641,7 +650,7 @@ result } -impl ItemCtxt<'tcx> { +impl<'tcx> ItemCtxt<'tcx> { /// Finds bounds from `hir::Generics`. This requires scanning through the /// AST. We do this to avoid having to convert *all* the bounds, which /// would create artificial cycles. Instead, we can only convert the @@ -666,7 +675,7 @@ Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), None => true, }) - .flat_map(|b| predicates_from_bound(self, ty, b)); + .flat_map(|b| predicates_from_bound(self, ty, b, ty::List::empty())); let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); let from_where_clauses = ast_generics @@ -685,15 +694,17 @@ } else { None }; + let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id); + bp.bounds .iter() .filter(|b| match assoc_name { Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), None => true, }) - .filter_map(move |b| bt.map(|bt| (bt, b))) + .filter_map(move |b| bt.map(|bt| (bt, b, bvars))) }) - .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); + .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars)); from_ty_params.chain(from_where_clauses).collect() } @@ -793,7 +804,10 @@ } // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} + 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 @@ -1182,8 +1196,7 @@ } fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); let (is_auto, unsafety) = match item.kind { hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), @@ -1233,7 +1246,7 @@ has_late_bound_regions: Option, } - impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { + impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1473,7 +1486,11 @@ // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // as they shouldn't be able to cause query cycle errors. Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - | Node::Variant(Variant { disr_expr: Some(ref constant), .. }) + if constant.hir_id() == hir_id => + { + Some(parent_def_id.to_def_id()) + } + Node::Variant(Variant { disr_expr: Some(ref constant), .. }) if constant.hir_id == hir_id => { Some(parent_def_id.to_def_id()) @@ -1489,15 +1506,18 @@ Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - impl_trait_fn.or_else(|| { - let parent_id = tcx.hir().get_parent_item(hir_id); - assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); - debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); - // Opaque types are always nested within another item, and - // inherit the generics of the item. - Some(tcx.hir().local_def_id(parent_id).to_def_id()) - }) + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + .. + }) => Some(fn_def_id.to_def_id()), + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + let parent_id = tcx.hir().get_parent_item(hir_id); + assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); + debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); + // Opaque types are always nested within another item, and + // inherit the generics of the item. + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } _ => None, }, @@ -1737,7 +1757,7 @@ } } -pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { +pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FnRetTy::Return(ty) = output { if is_suggestable_infer_ty(ty) { return Some(&*ty); @@ -1776,9 +1796,9 @@ let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); - let mut diag = bad_placeholder_type(tcx, visitor.0, "return type"); + let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type"); let ret_ty = fn_sig.skip_binder().output(); - if ret_ty != tcx.ty_error() { + if !ret_ty.references_error() { if !ret_ty.is_closure() { let ret_ty_str = match ret_ty.kind() { // Suggest a function pointer return type instead of a unique function definition @@ -1878,9 +1898,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); - - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().expect_item(hir_id).kind { + match tcx.hir().expect_item(def_id.expect_local()).kind { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); >::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) @@ -1890,9 +1908,8 @@ } fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); match &item.kind { hir::ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(span), @@ -2055,31 +2072,32 @@ generics } ItemKind::OpaqueTy(OpaqueTy { - bounds: _, - impl_trait_fn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + .. + }) => { + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: _, + origin: hir::OpaqueTyOrigin::TyAlias, + .. }) => { - if impl_trait_fn.is_some() { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } else { - // type-alias impl trait - generics - } + // type-alias impl trait + generics } _ => NO_GENERICS, @@ -2433,14 +2451,10 @@ astconv: &dyn AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, + bound_vars: &'tcx ty::List, ) -> Vec<(ty::Predicate<'tcx>, Span)> { let mut bounds = Bounds::default(); - astconv.add_bounds( - param_ty, - std::array::IntoIter::new([bound]), - &mut bounds, - ty::List::empty(), - ); + astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); bounds.predicates(astconv.tcx(), param_ty) } @@ -2843,7 +2857,7 @@ ); } else if attr.has_name(sym::linkage) { if let Some(val) = attr.value_str() { - codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); + codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, val.as_str())); } } else if attr.has_name(sym::link_section) { if let Some(val) = attr.value_str() { @@ -2888,7 +2902,7 @@ } } } else if attr.has_name(sym::instruction_set) { - codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) { + codegen_fn_attrs.instruction_set = match attr.meta_kind() { Some(MetaItemKind::List(ref items)) => match items.as_slice() { [NestedMetaItem::MetaItem(set)] => { let segments = @@ -2993,7 +3007,7 @@ if !attr.has_name(sym::inline) { return ia; } - match attr.meta().map(|i| i.kind) { + match attr.meta_kind() { Some(MetaItemKind::Word) => InlineAttr::Hint, Some(MetaItemKind::List(ref items)) => { inline_span = Some(attr.span); @@ -3006,9 +3020,9 @@ ) .emit(); InlineAttr::None - } else if list_contains_name(&items[..], sym::always) { + } else if list_contains_name(&items, sym::always) { InlineAttr::Always - } else if list_contains_name(&items[..], sym::never) { + } else if list_contains_name(&items, sym::never) { InlineAttr::Never } else { struct_span_err!( @@ -3032,7 +3046,7 @@ return ia; } let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit(); - match attr.meta().map(|i| i.kind) { + match attr.meta_kind() { Some(MetaItemKind::Word) => { err(attr.span, "expected one argument"); ia @@ -3042,9 +3056,9 @@ if items.len() != 1 { err(attr.span, "expected one argument"); OptimizeAttr::None - } else if list_contains_name(&items[..], sym::size) { + } else if list_contains_name(&items, sym::size) { OptimizeAttr::Size - } else if list_contains_name(&items[..], sym::speed) { + } else if list_contains_name(&items, sym::speed) { OptimizeAttr::Speed } else { err(items[0].span(), "invalid argument"); @@ -3227,7 +3241,7 @@ let hir_id = tcx.hir().local_def_id_to_hir_id(id); let node = tcx.hir().get(hir_id); if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir().get_parent_did(hir_id); let parent_item = tcx.hir().expect_item(parent_id); if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind { tcx.sess diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/expr_use_visitor.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/expr_use_visitor.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/expr_use_visitor.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/expr_use_visitor.rs 2022-02-23 04:07:21.000000000 +0000 @@ -229,8 +229,8 @@ } } - hir::ExprKind::Let(pat, ref expr, _) => { - self.walk_local(expr, pat, |t| t.borrow_expr(expr, ty::ImmBorrow)); + hir::ExprKind::Let(hir::Let { pat, init, .. }) => { + self.walk_local(init, pat, |t| t.borrow_expr(init, ty::ImmBorrow)); } hir::ExprKind::Match(ref discr, arms, _) => { @@ -482,7 +482,7 @@ } } - fn walk_struct_expr( + fn walk_struct_expr<'hir>( &mut self, fields: &[hir::ExprField<'_>], opt_with: &Option<&'hir hir::Expr<'_>>, @@ -705,7 +705,7 @@ /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing /// closure as the DefId. fn walk_captures(&mut self, closure_expr: &hir::Expr<'_>) { - fn upvar_is_local_variable( + fn upvar_is_local_variable<'tcx>( upvars: Option<&'tcx FxIndexMap>, upvar_id: &hir::HirId, body_owner_is_closure: bool, @@ -715,13 +715,14 @@ debug!("walk_captures({:?})", closure_expr); - let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id).to_def_id(); - let upvars = self.tcx().upvars_mentioned(self.body_owner); + let tcx = self.tcx(); + let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id).to_def_id(); + let upvars = tcx.upvars_mentioned(self.body_owner); // For purposes of this function, generator and closures are equivalent. let body_owner_is_closure = matches!( - self.tcx().type_of(self.body_owner.to_def_id()).kind(), - ty::Closure(..) | ty::Generator(..) + tcx.hir().body_owner_kind(tcx.hir().local_def_id_to_hir_id(self.body_owner)), + hir::BodyOwnerKind::Closure, ); // If we have a nested closure, we want to include the fake reads present in the nested closure. @@ -846,7 +847,7 @@ } } -fn is_multivariant_adt(ty: Ty<'tcx>) -> bool { +fn is_multivariant_adt(ty: Ty<'_>) -> bool { if let ty::Adt(def, _) = ty.kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need // to assume that more cases will be added to the variant in the future. This mean diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/impl_wf_check.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/impl_wf_check.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/impl_wf_check.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/impl_wf_check.rs 2022-02-23 04:07:21.000000000 +0000 @@ -76,7 +76,7 @@ min_specialization: bool, } -impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { if let hir::ItemKind::Impl(ref impl_) = item.kind { enforce_impl_params_are_constrained(self.tcx, item.def_id, impl_.items); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/lib.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/lib.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/lib.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/lib.rs 2022-02-23 04:07:21.000000000 +0000 @@ -58,11 +58,8 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(if_let_guard)] -#![feature(in_band_lifetimes)] #![feature(is_sorted)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(nll)] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/outlives/test.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/outlives/test.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/outlives/test.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/outlives/test.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/variance/test.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/variance/test.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/variance/test.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_typeck/src/variance/test.rs 2022-02-23 04:07:21.000000000 +0000 @@ -12,7 +12,7 @@ tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/needs_drop.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/needs_drop.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/needs_drop.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/needs_drop.rs 2022-02-23 04:07:21.000000000 +0000 @@ -147,8 +147,10 @@ Ok(tys) => tys, }; for required_ty in tys { - let required = - tcx.normalize_erasing_regions(self.param_env, required_ty); + let required = tcx + .try_normalize_erasing_regions(self.param_env, required_ty) + .unwrap_or(required_ty); + queue_type(self, required); } } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/ty.rs rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/ty.rs --- rustc-1.58.1+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/ty.rs 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/compiler/rustc_ty_utils/src/ty.rs 2022-02-23 04:07:21.000000000 +0000 @@ -2,10 +2,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{ - self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, -}; -use rustc_span::Span; +use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; +use rustc_span::{sym, Span}; use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( @@ -123,7 +121,7 @@ let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_id = tcx.hir().get_parent_item(id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let parent_item = tcx.hir().expect_item(parent_id); + let parent_item = tcx.hir().expect_item(parent_def_id); match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = @@ -158,8 +156,7 @@ } fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.defaultness } else { @@ -168,8 +165,7 @@ } fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.constness } else { @@ -202,8 +198,7 @@ } fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { - let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(id); + let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), @@ -251,7 +246,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -285,16 +280,85 @@ // issue #89334 predicates = tcx.expose_default_const_substs(predicates); - let unnormalized_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); + let local_did = def_id.as_local(); + let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.has_attr(def_id, sym::default_method_body_is_const) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + None => hir::Constness::NotConst, + }; + + let unnormalized_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + traits::Reveal::UserFacing, + constness, + ); - debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); - let body_id = def_id - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - .map_or(hir::CRATE_HIR_ID, |id| { - tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) - }); + let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| { + tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) + }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) } @@ -316,7 +380,7 @@ // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/config.toml.example rustc-1.59.0+dfsg1~ubuntu1~llvm/config.toml.example --- rustc-1.58.1+dfsg1~ubuntu1~llvm/config.toml.example 2022-01-20 17:48:09.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/config.toml.example 2022-02-23 04:07:21.000000000 +0000 @@ -488,9 +488,12 @@ # FIXME(#75760): Some UI tests fail when this option is enabled. #parallel-compiler = false -# The default linker that will be hard-coded into the generated compiler for -# targets that don't specify linker explicitly in their target specifications. -# Note that this is not the linker used to link said compiler. +# The default linker that will be hard-coded into the generated +# compiler for targets that don't specify a default linker explicitly +# in their target specifications. Note that this is not the linker +# used to link said compiler. It can also be set per-target (via the +# `[target.]` block), which may be useful in a cross-compilation +# setting. # # See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. #default-linker = (path) diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/changelog rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/changelog --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/changelog 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/changelog 2022-06-07 14:17:36.000000000 +0000 @@ -1,15 +1,64 @@ -rustc (1.58.1+dfsg1~ubuntu1~llvm-0ubuntu1~21.10.1) impish; urgency=medium +rustc (1.59.0+dfsg1~ubuntu1~llvm-1~ubuntu1~21.10.2) impish; urgency=medium - * Backport to impish + * d/p/u-revert-92419.patch: cherry-picked to fix a big performance + regression on s390x. + + -- Simon Chopin Tue, 07 Jun 2022 16:17:36 +0200 + +rustc (1.59.0+dfsg1~ubuntu1~llvm-1~ubuntu1~21.10.1) impish; urgency=medium + + * Backport to Impish (LP: #1968345) * Re-enable embedded LLVM: - Scrub -g from CFLAGS and CXXFLAGS in order to let rustbuild control whether LLVM is compiled with debug symbols - Adjust debian/watch to include +llvm in upstream version. - * d/p/ubuntu-llvm-riscv-insn-support.patch: cherry-picked to fix the rustc - 1.59 build - * d/copyright: exclude new openssl subcrates - -- Simon Chopin Thu, 28 Apr 2022 12:40:50 +0200 + -- Simon Chopin Fri, 29 Apr 2022 10:28:30 +0200 + +rustc (1.59.0+dfsg1-1~ubuntu1) kinetic; urgency=medium + + * Merge 1.59.0+dfsg1-1~exp1 from Debian experimental (LP: #1968345) + Remaining changes: + - Downgrade cargo from rustc Recommends to Suggests to make rustc promotable to + main. (LP: #1966200) + - New patch u-linkchecker-symlinks.patch to fix an issue in + the linkchecker triggered by our symlink to the system fonts dir + - d/control: Add fonts-nanum to the rust-doc deps + - d/control: Add the rust-doc deps as build-deps for the linkchecker tests + - Reduce parallelism on all arches other than riscv64 to avoid OOMs + during build. + - Explicitly disable LTO + - Add a self-build autopkgtest + - Ship the Cargo.lock file along with the compiler to identify which crates + were bundled in. + - d/p/ubuntu-disable-armhf-debuginfo-failures.patch: temporary to work + around the armhf debuginfo test failures + - d/p/ubuntu-ignore-arm-doctest.patch: Patch out the bad doctests for the + instruction_set errors + - d/p/ubuntu-fix-crossbeam-CVE-2022-23639.patch: cherry-pick to fix CVE-2022-23639 + amended to also patch the 0.7.2 version of the crate + - On i386, only build debuginfo for libstd + - Add a hack to ensure the stage0 compiler is extracted to the correct + location + - Build-Depend on libc6-dbg on armhf, to workaround a crash in ld.so + during some debuginfo tests + - Version the Build-Conflict on gdb-minimal as gdb now Provides it + - Adjust the rustc Breaks/Replaces libstd-rust-dev version to fix an + upgrade issue + - Add Build-Depends-Indep: libssl-dev + - Revert workaround for upstream bug #74786 + - Disable wasm build as build dependencies not currently available in + Ubuntu. + - Do not build windows cross compiler. + + -- Simon Chopin Fri, 29 Apr 2022 10:13:09 +0200 + +rustc (1.59.0+dfsg1-1~exp1) experimental; urgency=medium + + [ Fabian Grünbichler ] + * New upstream release + + -- Ximin Luo Tue, 29 Mar 2022 14:32:01 +0100 rustc (1.58.1+dfsg1~ubuntu1-0ubuntu2) jammy; urgency=medium @@ -20,6 +69,25 @@ -- Simon Chopin Fri, 01 Apr 2022 11:54:57 +0200 +rustc (1.58.1+dfsg1-1) unstable; urgency=medium + + * Upload to unstable. + + -- Ximin Luo Tue, 29 Mar 2022 12:23:46 +0100 + +rustc (1.58.1+dfsg1-1~exp1) experimental; urgency=medium + + [ Fabian Gruenbichler ] + * New upstream release. + + -- Ximin Luo Tue, 08 Mar 2022 11:32:29 +0000 + +rustc (1.57.0+dfsg1-1) unstable; urgency=medium + + * Upload to unstable. (Closes: #1005203) + + -- Ximin Luo Tue, 08 Mar 2022 10:51:18 +0000 + rustc (1.58.1+dfsg1~ubuntu1-0ubuntu1) jammy; urgency=medium * New upstream version. @@ -56,6 +124,18 @@ -- Simon Chopin Thu, 24 Feb 2022 13:41:38 +0100 +rustc (1.57.0+dfsg1-1~exp1) experimental; urgency=medium + + [ Simon Chopin ] + * d/p/d-bootstrap-rustflags.patch: remove the warnings bit, use the option + "deny-warnings = false" in d/config.toml.in instead + + [ Fabian Grünbichler ] + * Fix CVE-2022-21658 - std::fs::remove_dir_all TOCTOU symlink issue + * New upstream release. (Closes: #1005203) + + -- Fabian Grünbichler Thu, 03 Feb 2022 19:14:04 +0100 + rustc (1.57.0+dfsg1+llvm-0ubuntu2) jammy; urgency=medium * d/p/d-bootstrap-rustflags.patch: remove the warnings bit, use the option @@ -125,6 +205,7 @@ -- Michael Hudson-Doyle Tue, 14 Dec 2021 10:24:02 +1300 + rustc (1.56.0+dfsg1-2) unstable; urgency=medium * Update to debhelper 13. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/control rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/control --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/control 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/control 2022-06-07 14:07:32.000000000 +0000 @@ -14,8 +14,8 @@ dpkg-dev (>= 1.17.14), python3:native, cargo:native (>= 0.40.0) , - rustc:native (>= 1.57.0+dfsg) , - rustc:native (<= 1.58.1++) , + rustc:native (>= 1.58.0+dfsg) , + rustc:native (<= 1.59.0++) , cmake (>= 3.0) | cmake3, # needed by some vendor crates pkg-config, @@ -65,7 +65,7 @@ llvm-13, Suggests: # lld and clang are needed for wasm compilation - cargo (>= 0.58.0~~), cargo (<< 0.59.0~~), + cargo (>= 0.60.0~~), cargo (<< 0.61.0~~), lld-13, clang-13, Replaces: libstd-rust-dev (<< 1.26.2+dfsg1+llvm-0ubuntu1~~) Breaks: libstd-rust-dev (<< 1.26.2+dfsg1+llvm-0ubuntu1~~) @@ -82,7 +82,7 @@ generic programming and meta-programming, in both static and dynamic styles. -Package: libstd-rust-1.58 +Package: libstd-rust-1.59 Section: libs Architecture: any Multi-Arch: same @@ -109,7 +109,7 @@ Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends}, - libstd-rust-1.58 (= ${binary:Version}), + libstd-rust-1.59 (= ${binary:Version}), Description: Rust standard libraries - development files Rust is a curly-brace, block-structured expression language. It visually resembles the C language family, but differs significantly @@ -216,7 +216,7 @@ Architecture: any Multi-Arch: allowed Depends: ${misc:Depends}, ${shlibs:Depends}, - libstd-rust-1.58 (= ${binary:Version}) + libstd-rust-1.59 (= ${binary:Version}) Recommends: cargo Description: Rust linter Rust is a curly-brace, block-structured expression language. It @@ -271,7 +271,7 @@ rust-gdb (>= ${binary:Version}) | rust-lldb (>= ${binary:Version}), cargo, Recommends: - cargo (>= 0.57.0~~), cargo (<< 0.58.0~~) + cargo (>= 0.60.0~~), cargo (<< 0.61.0~~) Suggests: rust-doc (>= ${binary:Version}), rust-src (>= ${binary:Version}), diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/copyright rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/copyright --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/copyright 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/copyright 2022-06-01 08:48:08.000000000 +0000 @@ -6,7 +6,7 @@ src/llvm-emscripten # Fonts already in Debian, covered by d-rustdoc-use-system-font.patch # TODO make that patch, modify src/librustdoc/html/static/css/rustdoc.css - src/librustdoc/html/static/fonts/NanumBarun* + src/librustdoc/html/static/fonts/noto-sans-* # Pre-generated docs src/tools/rustfmt/docs # Proprietary doc formats @@ -42,6 +42,8 @@ vendor/mdbook/src/theme/playground_editor vendor/psm/src/arch/wasm32.o vendor/winapi-*/*/*.a +# Embedded submodule used for CI + library/stdarch/crates/intrinsic-test/acle # NPM packages we can't be bothered documenting licenses for vendor/tera/docs/node_modules # unused dependencies, generated by debian/prune-unused-deps @@ -49,11 +51,9 @@ vendor/addr2line vendor/adler-0.2.3 vendor/always-assert - vendor/anyhow-1.0.34 - vendor/anyhow-1.0.42 vendor/anymap - vendor/ar vendor/arbitrary + vendor/ar vendor/arrayvec-0.7.0 vendor/autocfg-1.0.0 vendor/backtrace @@ -63,20 +63,17 @@ vendor/bytesize vendor/cargo_metadata-0.14.0 vendor/cc-1.0.69 - vendor/chalk-derive - vendor/chalk-ir vendor/chalk-recursive - vendor/chalk-solve - vendor/commoncrypto-sys vendor/commoncrypto - vendor/core-foundation-sys + vendor/commoncrypto-sys vendor/core-foundation + vendor/core-foundation-sys vendor/countme vendor/cov-mark vendor/cranelift-bforest + vendor/cranelift-codegen vendor/cranelift-codegen-meta vendor/cranelift-codegen-shared - vendor/cranelift-codegen vendor/cranelift-entity vendor/cranelift-frontend vendor/cranelift-jit @@ -87,30 +84,30 @@ vendor/crossbeam-channel-0.5.0 vendor/crossbeam-utils-0.8.3 vendor/crypto-hash - vendor/curl-sys vendor/curl + vendor/curl-sys vendor/dashmap vendor/derive_arbitrary vendor/derive_more vendor/directories - vendor/dissimilar vendor/dot vendor/drop_bomb vendor/either-1.6.0 - vendor/enum-iterator-derive vendor/enum-iterator + vendor/enum-iterator-derive vendor/env_logger - vendor/expect-test + vendor/expect-test-1.0.1 vendor/filetime-0.2.14 vendor/flate2-1.0.16 - vendor/foreign-types-shared vendor/foreign-types + vendor/foreign-types-shared + vendor/fsevent-sys vendor/fs_extra-1.1.0 vendor/fs_extra - vendor/fsevent-sys vendor/fst-0.4.5 vendor/fst vendor/futures-0.1.29 + vendor/futures vendor/futures-channel vendor/futures-core vendor/futures-executor @@ -119,12 +116,10 @@ vendor/futures-sink vendor/futures-task vendor/futures-util - vendor/futures vendor/fwdansi vendor/getset - vendor/gimli - vendor/git2-curl vendor/git2 + vendor/git2-curl vendor/hashbrown-0.11.0 vendor/heck-0.3.1 vendor/hex-0.3.2 @@ -132,33 +127,31 @@ vendor/idna-0.1.5 vendor/idna-0.2.0 vendor/im-rc - vendor/inotify-sys vendor/inotify - vendor/instant-0.1.6 + vendor/inotify-sys + vendor/itertools-0.10.1 vendor/itoa-0.4.6 vendor/jod-thread vendor/json vendor/jsonrpc-client-transports - vendor/jsonrpc-core-client vendor/jsonrpc-core + vendor/jsonrpc-core-client vendor/jsonrpc-derive vendor/jsonrpc-ipc-server vendor/jsonrpc-pubsub vendor/jsonrpc-server-utils - vendor/kqueue-sys vendor/kqueue + vendor/kqueue-sys vendor/lazycell - vendor/libc-0.2.106 - vendor/libc-0.2.98 + vendor/libc-0.2.108 vendor/libgit2-sys vendor/libloading-0.6.7 - vendor/libloading + vendor/libloading-0.7.1 vendor/libmimalloc-sys vendor/libnghttp2-sys vendor/libssh2-sys vendor/libz-sys vendor/linked-hash-map - vendor/lock_api-0.4.1 vendor/lsp-codec vendor/lsp-server vendor/lsp-types-0.60.0 @@ -166,37 +159,35 @@ vendor/mach vendor/matches-0.1.8 vendor/measureme-9.1.2 - vendor/memchr-2.4.0 vendor/memmap2 vendor/mimalloc vendor/miniz_oxide-0.4.0 vendor/mio-0.7.13 vendor/mio + vendor/miow vendor/notify vendor/ntapi - vendor/object-0.26.0 vendor/object vendor/once_cell-1.7.2 vendor/oorandom - vendor/openssl-src vendor/openssl - vendor/openssl-sys vendor/openssl-probe + vendor/openssl-src + vendor/openssl-sys vendor/ordslice vendor/os_info vendor/parity-tokio-ipc - vendor/parking_lot-0.11.1 - vendor/parking_lot_core-0.8.3 vendor/paste vendor/percent-encoding-1.0.1 vendor/perf-event vendor/pin-project-lite-0.2.4 vendor/pin-utils vendor/pretty_env_logger + vendor/proc-macro2-1.0.30 vendor/proc-macro-crate vendor/proc-macro-hack vendor/proc-macro-nested - vendor/proc-macro2-1.0.30 + vendor/pulldown-cmark-0.8.0 vendor/pulldown-cmark-to-cmark vendor/quote-1.0.7 vendor/racer @@ -225,13 +216,13 @@ vendor/rustc-ap-rustc_session vendor/rustc-ap-rustc_span vendor/rustc-ap-rustc_target - vendor/rustc_version-0.3.3 vendor/rustc_version - vendor/salsa-macros + vendor/ryu-1.0.5 vendor/salsa + vendor/salsa-macros vendor/schannel - vendor/security-framework-sys vendor/security-framework + vendor/security-framework-sys vendor/semver-1.0.3 vendor/serde-1.0.125 vendor/serde_derive-1.0.125 @@ -243,30 +234,25 @@ vendor/signal-hook-registry vendor/sized-chunks vendor/slab - vendor/smallvec-1.6.1 vendor/smol_str vendor/snap-1.0.1 vendor/socket2 vendor/strip-ansi-escapes vendor/syn-1.0.80 - vendor/synstructure-0.12.4 vendor/target-lexicon vendor/text-size vendor/thread_local-1.0.1 vendor/threadpool + vendor/tikv-jemallocator vendor/tikv-jemalloc-ctl vendor/tikv-jemalloc-sys-0.4.1+5.2.1-patched vendor/tikv-jemalloc-sys - vendor/tikv-jemallocator vendor/tinyvec-0.3.4 + vendor/tokio vendor/tokio-stream vendor/tokio-util - vendor/tokio vendor/tower-service - vendor/tracing-0.1.28 - vendor/tracing-attributes-0.1.17 - vendor/tracing-subscriber-0.2.16 - vendor/tracing-tree-0.1.9 + vendor/typed-arena vendor/ungrammar vendor/unicode-bidi-0.3.4 vendor/unicode-normalization-0.1.13 @@ -277,11 +263,17 @@ vendor/vergen vendor/vte vendor/walkdir-2.3.1 + vendor/windows_aarch64_msvc + vendor/windows_i686_gnu + vendor/windows_i686_msvc + vendor/windows-sys + vendor/windows_x86_64_gnu + vendor/windows_x86_64_msvc vendor/write-json - vendor/xflags-macros vendor/xflags - vendor/xshell-macros + vendor/xflags-macros vendor/xshell + vendor/xshell-macros vendor/yaml-merge-keys vendor/yaml-rust # DO NOT EDIT above, AUTOGENERATED @@ -305,7 +297,7 @@ src/etc/* src/lib* src/rust* - src/stage0.txt + src/stage0.json src/tools/* src/test/* src/version @@ -316,41 +308,26 @@ 2012-2017 The Rust Project Developers (see AUTHORS.txt) License: MIT or Apache-2.0 -Files: library/backtrace/crates/backtrace-sys/src/libbacktrace/* -Copyright: 2012-2016 Free Software Foundation, Inc. -License: BSD-3-Clause -Comment: written by Ian Lance Taylor, Google. - -Files: - library/backtrace/crates/backtrace-sys/src/libbacktrace/filenames.h - library/backtrace/crates/backtrace-sys/src/libbacktrace/ltmain.sh -Copyright: 2000, 2001, 2007, 2010 Free Software Foundation, Inc. -License: GPL-2+ - -Files: library/std/src/memchr.rs -Copyright: 2015 Andrew Gallant, bluss and Nicolas Koch -License: MIT or Apache-2.0 - Files: library/std/src/sync/mpsc/mpsc_queue.rs library/std/src/sync/mpsc/spsc_queue.rs Copyright: 2010-2011 Dmitry Vyukov License: BSD-2-Clause -Files: src/librustdoc/html/static/FiraSans* +Files: src/librustdoc/html/static/fonts/FiraSans* Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A. License: SIL-OPEN-FONT -Files: src/librustdoc/html/static/SourceCodePro* -Copyright: 2010, 2012 Adobe Systems Incorporated +Files: src/librustdoc/html/static/fonts/NanumBarun* +Copyright: 2010 NAVER Corporation License: SIL-OPEN-FONT -Files: src/librustdoc/html/static/SourceSerifPro* -Copyright: 2014 Adobe Systems Incorporated +Files: src/librustdoc/html/static/fonts/SourceCodePro* +Copyright: 2010, 2012 Adobe Systems Incorporated License: SIL-OPEN-FONT -Files: src/librustdoc/html/static/main.js -Copyright: 2014 The Rust Project Developers -License: MIT or Apache-2.0 +Files: src/librustdoc/html/static/fonts/SourceSerif4* +Copyright: 2014-2021 Adobe Systems Incorporated +License: SIL-OPEN-FONT Files: vendor/compiler_builtins/* Copyright: 2016-2019 Jorge Aparicio @@ -367,16 +344,13 @@ Files: vendor/bitflags/* vendor/cc/* - vendor/cc-1*/* vendor/cmake/* - vendor/env_logger/* vendor/env_logger-0*/* vendor/getopts/* vendor/glob/* vendor/libc/* vendor/log/* vendor/regex/* - vendor/regex-1*/* vendor/regex-syntax/* vendor/rustc-hash/* vendor/time/* @@ -397,7 +371,6 @@ Files: vendor/string_cache/* vendor/string_cache_codegen/* - vendor/string_cache_shared/* vendor/unicode-bidi/* Copyright: 2015-2017 Alex Crichton 2015-2017 Keegan McAllister @@ -419,11 +392,9 @@ vendor/rand_core-0*/* vendor/rand_hc/* vendor/rand_hc-0*/* - vendor/rand_isaac/* vendor/rand_pcg/* - vendor/rand_pcg-0*/* vendor/rand_xorshift/* - vendor/rand_xorshift-0*/* + vendor/rand_xoshiro/* Copyright: 2010-2019 The Rand Project Developers 2010-2019 The Rust Project Developers License: MIT or Apache-2.0 @@ -439,15 +410,11 @@ vendor/flate2/* vendor/fnv/* vendor/jobserver/* - vendor/libz-sys/* vendor/lzma-sys/* - vendor/miow/* vendor/pkg-config/* vendor/proc-macro2/* - vendor/proc-macro2-0*/* vendor/rustc-demangle/* vendor/scoped-tls/* - vendor/socket2/* vendor/tar/* vendor/toml/* vendor/xz2/* @@ -470,14 +437,7 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/messense/rustc-test -Files: vendor/rustc-ap-*/* -Copyright: 2010-2020 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang/rust - -Files: - vendor/addr2line/* - vendor/addr2line-0*/* +Files: vendor/addr2line-0*/* Copyright: 2016-2021 Nick Fitzgerald 2016-2021 Philip Craig @@ -491,11 +451,6 @@ License: 0BSD or MIT or Apache-2.0 Comment: see https://github.com/jonas-schievink/adler.git -Files: vendor/adler32/* -Copyright: 2015-2020 Remi Rampin -License: Zlib -Comment: see https://github.com/remram44/adler32-rs - Files: vendor/ammonia/* Copyright: 2015-2018 Michael Howell License: MIT or Apache-2.0 @@ -516,36 +471,21 @@ License: MIT Comment: see https://github.com/ogham/rust-ansi-term -Files: vendor/anymap/* -Copyright: 2014-2018 Chris Morgan -License: MIT or Apache-2.0 -Comment: see https://github.com/chris-morgan/anymap - Files: vendor/aho-corasick/* vendor/memchr/* - vendor/utf8-ranges/* Copyright: 2015 Andrew Gallant 2015-2018 bluss License: MIT or Unlicense Comment: see upstream projects, - * https://github.com/docopt/docopt.rs * https://github.com/BurntSushi/aho-corasick * https://github.com/BurntSushi/rust-memchr - * https://github.com/BurntSushi/utf8-ranges - -Files: vendor/arrayref/* -Copyright: 2015-2018 David Roundy -License: BSD-2-Clause -Comment: see https://github.com/droundy/arrayref Files: vendor/array_tool/* Copyright: 2015-2018 Daniel P. Clark <6ftdan@gmail.com> License: MIT OR Apache-2.0 Comment: see https://github.com/danielpclark/array_tool -Files: - vendor/autocfg/* - vendor/autocfg-0*/* +Files: vendor/autocfg/* Copyright: 2018-2020 Josh Stone License: Apache-2.0 or MIT @@ -554,17 +494,6 @@ License: MIT Comment: see https://github.com/softprops/atty -Files: vendor/base64/* -Copyright: 2015-2020 Alice Maz - 2015-2020 Marshall Pierce -License: MIT or Apache-2.0 -Comment: see https://github.com/marshallpierce/rust-base64 - -Files: vendor/blake2b_simd/* -Copyright: 2018-2020 Jack O'Connor -License: MIT -Comment: see https://github.com/oconnor663/blake2_simd - Files: vendor/block-buffer/* vendor/block-buffer-0*/* @@ -600,61 +529,59 @@ Files: vendor/byteorder/* - vendor/fst/* vendor/globset/* vendor/ignore/* vendor/same-file/* vendor/termcolor/* vendor/walkdir/* vendor/winapi-util/* - vendor/wincolor/* Copyright: 2015-2020 Andrew Gallant License: Unlicense or MIT Comment: see https://github.com/BurntSushi/byteorder - see https://github.com/BurntSushi/fst see https://github.com/BurntSushi/same-file see https://github.com/BurntSushi/walkdir see https://github.com/BurntSushi/winapi-util see https://github.com/BurntSushi/ripgrep/tree/master/globset see https://github.com/BurntSushi/ripgrep/tree/master/ignore see https://github.com/BurntSushi/ripgrep/tree/master/termcolor - see https://github.com/BurntSushi/ripgrep/tree/master/wincolor + +Files: vendor/camino/* +Copyright: 2020-2022 Without Boats + 2020-2022 Ashley Williams + 2020-2022 Steve Klabnik + 2020-2022 Rain +License: MIT OR Apache-2.0 +Comment: see https://github.com/withoutboats/camino Files: vendor/cargo_metadata/* vendor/cargo_metadata-0*/* - vendor/log_settings/* Copyright: 2016-2020 Oliver Schneider License: MIT Comment: - see https://github.com/oli-obk/log_settings see https://github.com/oli-obk/cargo_metadata -Files: - vendor/c2-chacha/* - vendor/ppv-lite86/* +Files: vendor/cargo-platform/* +Copyright: 2019-2022 The Cargo Project Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-lang/cargo + +Files: vendor/ppv-lite86/* Copyright: 2019-2019 The CryptoCorrosion Contributors License: MIT or Apache-2.0 Comment: see https://github.com/cryptocorrosion/cryptocorrosion Files: - vendor/chalk-derive-0*/* - vendor/chalk-engine-0*/* - vendor/chalk-ir-0*/* - vendor/chalk-solve-0*/* vendor/chalk-derive/* vendor/chalk-engine/* vendor/chalk-ir/* - vendor/chalk-macros/* - vendor/chalk-recursive/* - vendor/chalk-rust-ir/* vendor/chalk-solve/* Copyright: - 2015-2020 Rust Compiler Team - 2015-2020 Chalk developers + 2015-2022 Rust Compiler Team + 2015-2022 Chalk developers License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang-nursery/chalk +Comment: see https://github.com/rust-lang/chalk Files: vendor/chrono/* Copyright: 2014-2018 Kang Seonghoon @@ -666,37 +593,11 @@ License: MIT Comment: see https://github.com/kbknapp/clap-rs.git -Files: - vendor/cloudabi-0*/* - vendor/cloudabi/* -Copyright: 2016-2020 Nuxi (https://nuxi.nl/) and contributors -License: BSD-2-Clause -Comment: see https://github.com/nuxinl/cloudabi - Files: vendor/colored/* Copyright: 2016-2020 Thomas Wickham License: MPL-2.0 Comment: see https://github.com/mackwic/colored -Files: vendor/console/* -Copyright: 2017-2020 Armin Ronacher -License: MIT -Comment: see https://github.com/mitsuhiko/console - -Files: vendor/constant_time_eq/* -Copyright: 2015-2020 Cesar Eduardo Barros -License: CC0-1.0 -Comment: see https://github.com/cesarb/constant_time_eq - -Files: - vendor/const_fn/* - vendor/pin-project-lite/* -Copyright: 2018-2021 Taiki Endo -License: Apache-2.0 or MIT -Comment: - see https://github.com/taiki-e/const_fn - see https://github.com/taiki-e/pin-project-lite - Files: vendor/crc32fast/* Copyright: 2018-2019 Sam Rijs 2018-2019 Alex Crichton @@ -710,23 +611,12 @@ vendor/crossbeam-epoch/* vendor/crossbeam-epoch-0*/* vendor/crossbeam-queue/* - vendor/crossbeam-queue-0*/* vendor/crossbeam-utils/* vendor/crossbeam-utils-0*/* Copyright: 2015-2021 The Crossbeam Project Developers License: MIT or Apache-2.0 Comment: see https://github.com/crossbeam-rs -Files: vendor/codespan/* -Copyright: 2018-2020 Brendan Zabarauskas -License: Apache-2.0 -Comment: see https://github.com/brendanzab/codespan - -Files: vendor/codespan-reporting/* -Copyright: 2018-2020 Brendan Zabarauskas -License: Apache-2.0 -Comment: see https://github.com/brendanzab/codespan - Files: vendor/cstr/* Copyright: 2018-2020 Xidorn Quan License: MIT @@ -737,13 +627,6 @@ License: Apache-2.0 OR MIT Comment: see https://github.com/mmastrac/rust-ctor -Files: - vendor/darling/* - vendor/darling_core/* - vendor/darling_macro/* -Copyright: 2017-2019 Ted Driggs -License: MIT - Files: vendor/datafrog/* Copyright: 2018 Frank McSherry @@ -765,21 +648,17 @@ Files: vendor/anyhow/* vendor/dissimilar/* - vendor/dtoa/* vendor/itoa/* vendor/quote/* - vendor/quote-0*/* vendor/syn/* - vendor/syn-0*/* -Copyright: 2016-2021 David Tolnay +Copyright: 2016-2022 David Tolnay License: MIT or Apache-2.0 Comment: see https://github.com/dtolnay/anyhow - see https://github.com/dtolnay/itoa see https://github.com/dtolnay/dissimilar + see https://github.com/dtolnay/itoa see https://github.com/dtolnay/quote see https://github.com/dtolnay/syn - see https://github.com/dtolnay/synom Files: vendor/arrayvec/* @@ -788,8 +667,6 @@ vendor/itertools/* vendor/itertools-0*/* vendor/maplit/* - vendor/nodrop/* - vendor/ordermap/* vendor/scopeguard/* Copyright: 2014-2020 bluss License: MIT or Apache-2.0 @@ -799,7 +676,6 @@ see https://github.com/bluss/arrayvec see https://github.com/bluss/fixedbitset see https://github.com/bluss/maplit - see https://github.com/bluss/ordermap see https://github.com/bluss/scopeguard Files: vendor/difference/* @@ -824,50 +700,25 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/xdg-rs/dirs -Files: vendor/drop_bomb/* -Copyright: 2018-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/drop_bomb - Files: vendor/elasticlunr-rs/* Copyright: 2017-2018 Matt Ickstadt License: MIT or Apache-2.0 Comment: see https://github.com/mattico/elasticlunr-rs -Files: - vendor/ena-0*/* - vendor/ena/* +Files: vendor/ena/* Copyright: 2015-2020 Niko Matsakis License: MIT or Apache-2.0 Comment: see https://github.com/nikomatsakis/ena -Files: vendor/encode_unicode/* -Copyright: 2016-2020 Torbjørn Birch Moltu -License: MIT or Apache-2.0 -Comment: see https://github.com/tormol/encode_unicode - -Files: - vendor/error-chain/* -Copyright: 2016-2017 Brian Anderson - 2016-2017 Paul Colomiets - 2016-2017 Colin Kiegel - 2016-2017 Yamakaky -License: MIT or Apache-2.0 -Comment: see https://github.com/brson/error-chain - Files: vendor/expect-test/* -Copyright: 2017-2020 rust-analyzer developers +Copyright: 2020-2022 rust-analyzer developers License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-analyzer/rust-analyzer +Comment: see https://github.com/rust-analyzer/expect-test -Files: - vendor/failure/* - vendor/failure_derive/* -Copyright: 2017-2018 Without Boats -License: MIT OR Apache-2.0 -Comment: - see https://github.com/withoutboats/failure - see https://github.com/withoutboats/failure_derive +Files: vendor/fallible-iterator/* +Copyright: 2016-2019 Steven Fackler +License: MIT or Apache-2.0 +Comment: see https://github.com/sfackler/rust-fallible-iterator Files: vendor/fortanix-sgx-abi/* Copyright: 2015-2019 Jethro Beekman @@ -879,25 +730,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/andrewhickman/fs-err -Files: - vendor/fsevent/* - vendor/fsevent-sys/* -Copyright: 2015-2020 Pierre Baillet -License: MIT -Comment: see https://github.com/octplane/fsevent-rust - -Files: vendor/fs_extra/* -Copyright: 2017-2018 Denis Kurilenko -License: MIT -Comment: see https://github.com/webdesus/fs_extra - -Files: - vendor/fuchsia-zircon/* - vendor/fuchsia-zircon-sys/* -Copyright: 2014-2018 Raph Levien -License: BSD-3-Clause -Comment: see https://fuchsia.googlesource.com/garnet/ - Files: vendor/futf/* Copyright: 2015-2018 Keegan McAllister License: MIT or Apache-2.0 @@ -913,8 +745,8 @@ Comment: see https://github.com/fizyk20/generic-array.git Files: - vendor/gimli/* vendor/gimli-0*/* + vendor/gimli/* Copyright: 2016-2021 Nick Fitzgerald 2016-2021 Philip Craig @@ -926,15 +758,6 @@ License: MIT Comment: see https://github.com/gilnaa/globwalk -Files: vendor/goblin/* -Copyright: 2016-2020 m4b - 2016-2020 seu - 2016-2020 Will Glynn - 2016-2020 Philip Craig - 2016-2020 Lzu Tao -License: MIT -Comment: see https://github.com/m4b/goblin - Files: vendor/gsgdt/* Copyright: 2020 Vishnunarayan K I License: MIT or Apache-2.0 @@ -968,12 +791,9 @@ License: MIT or Apache-2.0 Comment: see https://github.com/servo/html5ever -Files: vendor/home/* -Copyright: 2017-2020 Brian Anderson -License: MIT OR Apache-2.0 -Comment: see https://github.com/brson/home - -Files: vendor/humantime-*/* +Files: + vendor/humantime/* + vendor/humantime-*/* Copyright: 2016-2018 Paul Colomiets 2016 The humantime Developers @@ -981,11 +801,6 @@ 2005-2013 Rich Felker License: MIT or Apache-2.0 -Files: vendor/ident_case/* -Copyright: 2017-2019 Ted Driggs -License: MIT or Apache-2.0 -Comment: see https://github.com/TedDriggs/ident_case - Files: vendor/if_chain/* Copyright: 2016-2020 Chris Wong License: MIT or Apache-2.0 @@ -995,7 +810,6 @@ vendor/form_urlencoded/* vendor/idna/* vendor/percent-encoding/* - vendor/percent-encoding-1*/* vendor/url/* Copyright: 2013-2021 The rust-url developers License: MIT or Apache-2.0 @@ -1007,63 +821,24 @@ License: Apache-2.0 or MIT Comment: see https://github.com/bluss/indexmap -Files: vendor/inotify/* -Copyright: 2014-2020 Hanno Braun - 2014-2020 Félix Saparelli - 2014-2020 Cristian Kubis - 2014-2020 Frank Denis -License: ISC -Comment: see https://github.com/hannobraun/inotify - -Files: vendor/inotify-sys/* -Copyright: 2017-2020 Hanno Braun -License: ISC -Comment: see https://github.com/inotify-rs/inotify-sys - -Files: vendor/insta/* -Copyright: 2019-2020 Armin Ronacher -License: Apache-2.0 -Comment: see https://github.com/mitsuhiko/insta +Files: + vendor/indoc/* + vendor/unindent/* +Copyright: 2016-2022 David Tolnay +License: MIT OR Apache-2.0 +Comment: see https://github.com/dtolnay/indoc Files: vendor/instant/* Copyright: 2019-2020 sebcrozet License: BSD-3-Clause Comment: see https://github.com/sebcrozet/instant -Files: vendor/is-match/* - vendor/toml-query/* -Copyright: 2017-2018 Matthias Beyer -License: MPL-2.0 -Comment: see https://github.com/matthiasbeyer/is-match - see https://github.com/matthiasbeyer/toml-query - -Files: vendor/jemallocator/* -Copyright: 2016-2019 Alex Crichton - 2016-2019 Gonzalo Brito Gadeschi - 2016-2019 Simon Sapin - 2016-2019 Steven Fackler -License: MIT or Apache-2.0 -Comment: see https://github.com/gnzlbg/jemallocator - -Files: vendor/jemalloc-ctl/* -Copyright: 2016-2019 Steven Fackler - 2016-2019 Gonzalo Brito Gadeschi -License: MIT or Apache-2.0 -Comment: see https://github.com/gnzlbg/jemallocator - -Files: vendor/jod-thread/* -Copyright: 2019-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/jod-thread - Files: vendor/jsonpath_lib/* Copyright: 2018-2021 Changseok Han License: MIT Comment: see https://github.com/freestrings/jsonpath -Files: - vendor/lazy_static/* - vendor/lazy_static-0*/* +Files: vendor/lazy_static/* Copyright: 2014-2018 Marvin Löbel License: MIT or Apache-2.0 Comment: @@ -1071,7 +846,7 @@ see https://github.com/Kimundi/owning-ref-rs Files: vendor/libloading/* -Copyright: 2015-2020 Simonas Kazlauskas +Copyright: 2015-2022 Simonas Kazlauskas License: ISC Comment: see https://github.com/nagisa/rust_libloading/ @@ -1080,25 +855,7 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/rust-lang-nursery/libm -Files: vendor/linked-hash-map/* -Copyright: 2015-2020 Stepan Koltsov - 2015-2020 Andrew Paseltiner -License: MIT or Apache-2.0 -Comment: see https://github.com/contain-rs/linked-hash-map - -Files: vendor/lsp-server/* -Copyright: 2019-2020 rust-analyzer developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-analyzer/lsp-server - -Files: vendor/lsp-types/* -Copyright: 2016-2020 Markus Westerlind - 2016-2020 Bruno Medeiros -License: MIT -Comment: see https://github.com/gluon-lang/lsp-types - -Files: - vendor/mac/* +Files: vendor/mac/* Copyright: 2014-2017 Jonathan Reem License: MIT Comment: @@ -1125,31 +882,18 @@ License: MPL-2.0 Comment: see https://github.com/azerupi/mdBook -Files: - vendor/measureme/* - vendor/measureme-0*/* +Files: vendor/measureme/* Copyright: 2019-2020 Wesley Wiser 2019-2020 Michael Woerister License: MIT OR Apache-2.0 Comment: see https://github.com/rust-lang/measureme -Files: vendor/memmap/* -Copyright: 2015-2018 Dan Burkert -License: MIT or Apache-2.0 -Comment: see https://github.com/danburkert/memmap-rs - Files: vendor/memmap2-0*/* Copyright: 2015-2021 Dan Burkert 2015-2021 Evgeniy Reizner License: MIT or Apache-2.0 Comment: see https://github.com/RazrFalcon/memmap2-rs -Files: vendor/memmap2/* -Copyright: 2015-2021 Dan Burkert - 2015-2021 Evgeniy Reizner -License: MIT or Apache-2.0 -Comment: see https://github.com/RazrFalcon/memmap2-rs - Files: vendor/memoffset/* vendor/memoffset-0*/* @@ -1158,13 +902,6 @@ Comment: see https://github.com/Gilnaa/memoffset Files: - vendor/merge/* - vendor/merge_derive/* -Copyright: 2020-2020 Robin Krahl -License: Apache-2.0 OR MIT -Comment: see https://git.sr.ht/~ireas/merge-rs - -Files: vendor/macro-utils/* vendor/minifier/* Copyright: 2017-2018 Guillaume Gomez @@ -1179,21 +916,10 @@ License: MIT Comment: see https://github.com/Frommi/miniz_oxide -Files: vendor/mio/* -Copyright: 2014-2020 Carl Lerche -License: MIT -Comment: see https://github.com/tokio-rs/mio - -Files: vendor/mio-extras/* -Copyright: 2017-2020 Carl Lerche - 2017-2020 David Hotham -License: MIT OR Apache-2.0 -Comment: see https://github.com/dimbleby/mio-extras - -Files: vendor/net2/* -Copyright: 2015-2020 Alex Crichton +Files: vendor/miow-0.3.7/* +Copyright: 2014-2021 Alex Crichton License: MIT or Apache-2.0 -Comment: see https://github.com/deprecrated/net2-rs +Comment: see https://github.com/yoshuawuyts/miow Files: vendor/new_debug_unreachable/* Copyright: 2014-2018 Matt Brubeck @@ -1201,35 +927,22 @@ License: MIT Comment: see https://github.com/mbrubeck/rust-debug-unreachable -Files: vendor/notify/* -Copyright: 2014-2020 Félix Saparelli - 2014-2020 Daniel Faust -License: CC0-1.0 -Comment: see https://github.com/notify-rs/notify.git - Files: vendor/num_cpus/* Copyright: 2015 Sean McArthur License: MIT Comment: see https://github.com/seanmonstar/num_cpus -Files: - vendor/object-0*/* - vendor/object/* +Files: vendor/object-0*/* Copyright: 2016-2020 Nick Fitzgerald 2016-2020 Philip Craig License: Apache-2.0 or MIT Comment: see https://github.com/gimli-rs/object -Files: vendor/oorandom/* -Copyright: 2019-2020 Simon Heath -License: MIT -Comment: see https://sr.ht/~icefox/oorandom/ - -Files: vendor/open/* -Copyright: 2015-2017 Sebastian Thiel -License: MIT -Comment: see https://github.com/Byron/open-rs +Files: vendor/odht/* +Copyright: 2021 Michael Woerister +License: Apache-2.0 or MIT +Comment: see https://github.com/rust-lang/odht Files: vendor/opener/* Copyright: 2018-2020 Brian Bowman @@ -1248,15 +961,10 @@ Files: vendor/hashbrown/* - vendor/hashbrown-0*/* vendor/lock_api/* - vendor/lock_api-0*/* vendor/thread_local/* - vendor/thread_local-0*/* vendor/parking_lot/* - vendor/parking_lot-0*/* vendor/parking_lot_core/* - vendor/parking_lot_core-0*/* Copyright: 2016-2019 Amanieu d'Antras License: MIT or Apache-2.0 Comment: @@ -1270,21 +978,12 @@ License: MIT or Apache-2.0 Comment: see https://github.com/rust-lang-nursery/packed_simd -Files: - vendor/paste/* - vendor/paste-impl/* -Copyright: 2018-2020 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/paste - Files: vendor/pathdiff/* Copyright: 2017-2020 Manish Goregaokar License: MIT or Apache-2.0 Comment: see https://github.com/Manishearth/pathdiff -Files: - vendor/perf-event/* - vendor/perf-event-open-sys/* +Files: vendor/perf-event-open-sys/* Copyright: 2019-2020 Jim Blandy License: MIT OR Apache-2.0 Comment: see https://github.com/jimblandy/perf-event.git @@ -1300,11 +999,6 @@ see https://github.com/dragostis/pest see https://github.com/pest-parser/pest -Files: vendor/pico-args/* -Copyright: 2019-2020 Evgeniy Reizner -License: MIT -Comment: see https://github.com/RazrFalcon/pico-args - Files: vendor/polonius-engine/* Copyright: 2018-2018 The Rust Project Developers 2018-2018 Polonius Developers @@ -1326,10 +1020,11 @@ License: MIT Comment: see https://github.com/sfackler/rust-phf -Files: vendor/plain/* -Copyright: 2017-2020 jzr -License: MIT or Apache-2.0 -Comment: see https://github.com/randomites/plain +Files: vendor/pin-project-lite/* +Copyright: 2018-2021 Taiki Endo +License: Apache-2.0 or MIT +Comment: + see https://github.com/taiki-e/pin-project-lite Files: vendor/precomputed-hash/* Copyright: 2017-2017 Emilio Cobos Álvarez @@ -1349,29 +1044,16 @@ License: MIT OR Apache-2.0 Comment: see https://gitlab.com/CreepySkeleton/proc-macro-error -Files: vendor/proc-macro-hack/* -Copyright: 2016-2020 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/proc-macro-hack - Files: vendor/psm/* Copyright: 2015-2020 Simonas Kazlauskas License: MIT or Apache-2.0 Comment: see https://github.com/rust-lang/stacker/ -Files: - vendor/pulldown-cmark/* - vendor/pulldown-cmark-0*/* +Files: vendor/pulldown-cmark/* Copyright: 2015-2017 Raph Levien License: MIT Comment: see https://github.com/google/pulldown-cmark -Files: vendor/pulldown-cmark-to-cmark/* -Copyright: 2018-2020 Sebastian Thiel - 2018-2020 Dylan Owen -License: Apache-2.0 -Comment: see https://github.com/Byron/pulldown-cmark-to-cmark - Files: vendor/punycode/* Copyright: 2015-2019 mcarton License: MIT @@ -1403,34 +1085,23 @@ see https://github.com/rayon-rs/rayon see https://github.com/Zoxc/rayon/tree/rustc -Files: - vendor/redox_users/* - vendor/redox_users-0*/* +Files: vendor/redox_users/* Copyright: 2017-2021 Jose Narvaez 2017-2021 Wesley Hershberger License: MIT Comment: see https://gitlab.redox-os.org/redox-os/users -Files: - vendor/redox_syscall/* - vendor/redox_syscall-0*/* - vendor/redox_termios/* +Files: vendor/redox_syscall/* Copyright: 2016-2021 Jeremy Soller License: MIT Comment: see https://github.com/redox-os/syscall - see https://github.com/redox-os/termios Files: vendor/regex-automata/* Copyright: 2018-2020 Andrew Gallant License: Unlicense or MIT Comment: see https://github.com/BurntSushi/regex-automata -Files: vendor/relative-path/* -Copyright: 2017-2020 John-John Tedro -License: MIT or Apache-2.0 -Comment: see https://github.com/udoprog/relative-path - Files: vendor/remove_dir_all/* Copyright: 2017-2018 Aaronepower License: MIT or Apache-2.0 @@ -1443,11 +1114,6 @@ Comment: see https://github.com/nrc/rls-span see https://github.com/nrc/rls-data -Files: vendor/rowan/* -Copyright: 2018-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/rowan - Files: vendor/rustc-semver/* Copyright: 2020-2020 flip1995 License: MIT OR Apache-2.0 @@ -1458,11 +1124,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/rust-lang/rust-clippy -Files: vendor/rustc_version/* -Copyright: 2015-2018 Marvin Löbel -License: MIT or Apache-2.0 -Comment: see https://github.com/Kimundi/rustc-version-rs - Files: vendor/rustfix/* vendor/rustfix-0*/* @@ -1483,25 +1144,8 @@ Comment: see https://github.com/dtolnay/ryu Files: - vendor/salsa/* - vendor/salsa-macros/* -Copyright: 2018-2020 Salsa developers -License: Apache-2.0 OR MIT -Comment: see https://github.com/salsa-rs/salsa - -Files: - vendor/scroll/* - vendor/scroll_derive/* -Copyright: 2016-2020 m4b - 2016-2020 Ted Mielczarek - 2016-2020 Systemcluster @@ -1525,17 +1169,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/serde-rs/serde -Files: - vendor/serde_repr/* - vendor/serde_yaml/* -Copyright: - 2019-2020 David Tolnay - 2016-2020 David Tolnay -License: MIT OR Apache-2.0 -Comment: - see https://github.com/dtolnay/serde-repr - see https://github.com/dtolnay/serde-yaml - Files: vendor/sharded-slab/* Copyright: 2019-2020 Eliza Weisman License: MIT @@ -1556,18 +1189,11 @@ License: MIT or Apache-2.0 Comment: see https://github.com/jedisct1/rust-siphash -Files: - vendor/smallvec-0*/* - vendor/smallvec/* +Files: vendor/smallvec/* Copyright: 2015-2020 Simon Sapin License: MPL-2.0 Comment: see https://github.com/servo/rust-smallvec -Files: vendor/smol_str/* -Copyright: 2018-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/smol_str - Files: vendor/snap/* Copyright: 2016-2020 Andrew Gallant License: BSD-3-Clause @@ -1603,14 +1229,7 @@ Copyright: 2015-2018 Peter Glotfelty License: MIT -Files: vendor/superslice/* -Copyright: 2017-2019 Alkis Evlogimenos -License: Apache-2.0 -Comment: see https://github.com/alkis/superslice-rs - -Files: - vendor/synstructure/* - vendor/synstructure-0*/* +Files: vendor/synstructure/* Copyright: 2016-2019 Nika Layzell License: MIT @@ -1645,50 +1264,16 @@ License: MIT or Apache-2.0 Comment: see https://github.com/Stebalien/term -Files: vendor/termion/* -Copyright: 2016-2017 ticki - 2016-2017 gycos - 2016-2017 IGI-111 -License: MIT -Comment: see https://github.com/ticki/termion - -Files: vendor/terminal_size/* -Copyright: 2015-2020 Andrew Chin -License: MIT OR Apache-2.0 -Comment: see https://github.com/eminence/terminal-size - -Files: vendor/termios/* -Copyright: 2015-2020 David Cuddeback -License: MIT -Comment: see https://github.com/dcuddeback/termios-rs - Files: vendor/termize/* Copyright: 2016-2020 Yuki Okushi License: MIT or Apache-2.0 Comment: see https://github.com/JohnTitor/termize -Files: vendor/term_size/* -Copyright: 2016-2018 Kevin K. - 2016-2018 Benjamin Sago -License: MIT or Apache-2.0 -Comment: see https://github.com/kbknapp/term_size-rs.git - -Files: vendor/text-size/* -Copyright: 2018-2020 Aleksey Kladov - 2018-2020 Christopher Durham (CAD97) -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-analyzer/text-size - Files: vendor/textwrap/* Copyright: 2016-2017 Martin Geisler License: MIT Comment: see https://github.com/mgeisler/textwrap -Files: vendor/thin-dst/* -Copyright: 2019-2020 Christopher Durham (CAD97) -License: MIT OR Apache-2.0 -Comment: see https://github.com/cad97/thin-dst - Files: vendor/thiserror/* vendor/thiserror-impl/* @@ -1696,12 +1281,10 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/dtolnay/thiserror -Files: vendor/threadpool/* -Copyright: 2015-2020 The Rust Project Developers - 2015-2020 Corey Farwell - 2015-2020 Stefan Schindler -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-threadpool/rust-threadpool +Files: vendor/thorin-dwp/* +Copyright: 2021-2022 David Wood +License: MIT OR Apache-2.0 +Comment: see https://github.com/davidtwco/thorin Files: vendor/tinyvec/* Copyright: 2020 Lokathor @@ -1713,17 +1296,16 @@ License: MIT or Apache-2.0 or Zlib Comment: see https://github.com/Soveu/tinyvec_macros -Files: vendor/toml-query_derive/* -Copyright: 2017-2019 Matthias Beyer -License: MPL-2.0 -Comment: see https://github.com/matthiasbeyer/toml-query +Files: vendor/topological-sort/* +Copyright: 2015-2018 gifnksm +License: MIT OR Apache-2.0 +Comment: see https://github.com/gifnksm/topological-sort-rs Files: vendor/tracing/* vendor/tracing-attributes/* vendor/tracing-core/* vendor/tracing-log/* - vendor/tracing-serde/* vendor/tracing-subscriber/* Copyright: 2018-2020 Eliza Weisman @@ -1744,9 +1326,7 @@ License: MIT or Apache-2.0 Comment: see https://github.com/paholg/typenum -Files: - vendor/version_check/* - vendor/version_check-0.1.5/* +Files: vendor/version_check/* Copyright: 2017-2019 Sergio Benitez License: MIT or Apache-2.0 Comment: see https://github.com/SergioBenitez/version_check @@ -1754,18 +1334,12 @@ Files: vendor/ucd-parse/* vendor/ucd-trie/* - vendor/ucd-util/* Copyright: 2017-2020 Andrew Gallant License: MIT or Apache-2.0 Comment: see https://github.com/BurntSushi/rucd see https://github.com/BurntSushi/ucd-generate -Files: vendor/ungrammar/* -Copyright: 2020-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/ungrammar - Files: vendor/unicase/* Copyright: 2014-2019 Sean McArthur License: MIT or Apache-2.0 @@ -1776,6 +1350,11 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/swgillespie/unicode-categories +Files: vendor/unic-*/* +Copyright: 2017-2022 The UNIC Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/open-i18n/rust-unic/ + Files: vendor/unicode-normalization/* vendor/unicode-segmentation/* @@ -1787,9 +1366,7 @@ see https://github.com/unicode-rs/unicode-segmentation see https://github.com/unicode-rs/unicode-width -Files: - vendor/unicode-xid/* - vendor/unicode-xid-0*/* +Files: vendor/unicode-xid/* Copyright: 2015-2017 erick.tryzelaar 2015-2017 kwantam License: MIT or Apache-2.0 @@ -1817,11 +1394,6 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/SimonSapin/rust-utf8 -Files: vendor/vcpkg/* -Copyright: 2017-2019 Jim McGrath -License: MIT or Apache-2.0 -Comment: see https://github.com/mcgoo/vcpkg-rs - Files: vendor/vec_map/* Copyright: 2015-2017 Alexis Beingessner 2015-2017 Andrew Paseltiner @@ -1830,18 +1402,12 @@ License: MIT or Apache-2.0 Comment: see https://github.com/contain-rs/vec-map -Files: - vendor/wasi-0*/* - vendor/wasi/* +Files: vendor/wasi/* Copyright: 2019-2020 The Cranelift Project Developers License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT Comment: see https://github.com/CraneStation/rust-wasi -Files: - vendor/kernel32-sys/* - vendor/winapi/* - vendor/winapi-0*/* - vendor/winapi-build/* +Files: vendor/winapi/* Copyright: 2014-2019 Peter Atashian 2014-2019 winapi-rs developers @@ -1853,11 +1419,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/retep998/winapi-rs -Files: vendor/write-json/* -Copyright: 2020-2020 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/write-json - Files: vendor/xattr/* Copyright: 2015-2017 Steven Allen License: MIT or Apache-2.0 @@ -1868,9 +1429,7 @@ License: MIT or Apache-2.0 Comment: see https://github.com/servo/html5ever -Files: - vendor/yaml-rust-0*/* - vendor/yaml-rust/* +Files: vendor/yaml-rust-0*/* Copyright: 2015-2020 Yuheng Chen License: MIT or Apache-2.0 Comment: see https://github.com/chyh1990/yaml-rust diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.install rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.install --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.install 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -usr/lib/${DEB_HOST_MULTIARCH}/ diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.lintian-overrides rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.lintian-overrides --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.lintian-overrides 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.58.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -# "libstd" just seemed too generic -libstd-rust-1.58 binary: package-name-doesnt-match-sonames -libstd-rust-1.58 binary: sharedobject-in-library-directory-missing-soname - -# Rust doesn't use dev shlib symlinks nor any of the other shlib support stuff -libstd-rust-1.58 binary: dev-pkg-without-shlib-symlink -libstd-rust-1.58 binary: shlib-without-versioned-soname -libstd-rust-1.58 binary: unused-shlib-entry-in-control-file - -# Libraries that use libc symbols (libterm, libstd, etc) *are* linked -# to libc. Lintian gets upset that some Rust libraries don't need -# libc, boo hoo. -libstd-rust-1.58 binary: library-not-linked-against-libc diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.install rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.install --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.install 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.install 2022-06-07 14:07:32.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/${DEB_HOST_MULTIARCH}/ diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.lintian-overrides rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.lintian-overrides --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-1.59.lintian-overrides 2022-06-01 08:48:08.000000000 +0000 @@ -0,0 +1,13 @@ +# "libstd" just seemed too generic +libstd-rust-1.59 binary: package-name-doesnt-match-sonames +libstd-rust-1.59 binary: sharedobject-in-library-directory-missing-soname + +# Rust doesn't use dev shlib symlinks nor any of the other shlib support stuff +libstd-rust-1.59 binary: dev-pkg-without-shlib-symlink +libstd-rust-1.59 binary: shlib-without-versioned-soname +libstd-rust-1.59 binary: unused-shlib-entry-in-control-file + +# Libraries that use libc symbols (libterm, libstd, etc) *are* linked +# to libc. Lintian gets upset that some Rust libraries don't need +# libc, boo hoo. +libstd-rust-1.59 binary: library-not-linked-against-libc diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev.lintian-overrides rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev.lintian-overrides --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev.lintian-overrides 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev.lintian-overrides 2022-06-01 08:48:08.000000000 +0000 @@ -2,6 +2,9 @@ libstd-rust-dev binary: arch-dependent-file-not-in-arch-specific-directory usr/lib/rustlib/*/lib/lib*.rlib libstd-rust-dev binary: breakout-link usr/lib/rustlib/*/lib/lib*.so -> usr/lib/*/lib*.so +# lintian doesn't understand rlib files +libstd-rust-dev binary: no-code-sections [*.rlib] + # See debhelper bug #875780. This override is commented out because it's not # always needed, but we want it here for documentation purposes. Basically, # if you see it then you probably don't need to worry about it. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-wasm32.lintian-overrides rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-wasm32.lintian-overrides --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-wasm32.lintian-overrides 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-wasm32.lintian-overrides 2022-06-01 08:48:08.000000000 +0000 @@ -1,3 +1,8 @@ # wasm object files count as arch-independent for now, # at least until we starting offering Debian in wasm libstd-rust-dev-wasm32 binary: arch-independent-package-contains-binary-or-object usr/lib/rustlib/wasm32-*/lib/lib*.rlib +libstd-rust-dev-wasm32 binary: arch-independent-package-contains-binary-or-object usr/lib/rustlib/wasm32-*/lib/self-contained/libc.a + +# lintian doesn't understand rlib files +libstd-rust-dev-wasm32 binary: no-code-sections [*.rlib] +libstd-rust-dev-wasm32 binary: no-code-sections [usr/lib/rustlib/wasm32-*/lib/self-contained/libc.a] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-windows.lintian-overrides rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-windows.lintian-overrides --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-windows.lintian-overrides 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/libstd-rust-dev-windows.lintian-overrides 2022-06-01 08:48:08.000000000 +0000 @@ -2,3 +2,7 @@ libstd-rust-dev-windows binary: arch-dependent-file-not-in-arch-specific-directory usr/lib/rustlib/*/lib/lib*.rlib libstd-rust-dev-windows binary: arch-dependent-file-not-in-arch-specific-directory usr/lib/rustlib/*/lib/lib*.a libstd-rust-dev-windows binary: executable-not-elf-or-script usr/lib/rustlib/*/lib/*.dll + +# lintian doesn't understand these files +libstd-rust-dev-windows binary: no-code-sections [*.rlib] +libstd-rust-dev-windows binary: no-code-sections [usr/lib/rustlib/x86_64-pc-windows-gnu/lib/lib*.dll.a] diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0000-ignore-removed-submodules.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0000-ignore-removed-submodules.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0000-ignore-removed-submodules.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0000-ignore-removed-submodules.patch 2022-06-01 08:48:08.000000000 +0000 @@ -3,20 +3,21 @@ Subject: d-0000-ignore-removed-submodules --- - Cargo.toml | 26 -------------------------- - src/bootstrap/bootstrap.py | 4 ---- - src/bootstrap/builder.rs | 7 +------ - src/bootstrap/doc.rs | 1 - - src/bootstrap/test.rs | 12 +----------- - src/tools/clippy/Cargo.toml | 5 ----- - src/tools/rustfmt/Cargo.toml | 9 ++------- - src/tools/rustfmt/src/cargo-fmt/main.rs | 2 +- - src/tools/tidy/src/deps.rs | 4 ++-- - 9 files changed, 7 insertions(+), 63 deletions(-) + Cargo.toml | 27 --------------------------- + src/bootstrap/bootstrap.py | 4 ---- + src/bootstrap/builder.rs | 7 +------ + src/bootstrap/doc.rs | 1 - + src/bootstrap/test.rs | 12 +----------- + src/tools/clippy/Cargo.toml | 5 ----- + src/tools/rustfmt/Cargo.toml | 5 ----- + src/tools/tidy/src/deps.rs | 4 ++-- + 8 files changed, 4 insertions(+), 61 deletions(-) +diff --git a/Cargo.toml b/Cargo.toml +index cae48d7..6ab0782 100644 --- a/Cargo.toml +++ b/Cargo.toml -@@ -17,22 +17,12 @@ +@@ -17,25 +17,14 @@ members = [ "src/tools/tidy", "src/tools/tier-check", "src/tools/build-manifest", @@ -38,8 +39,11 @@ - "src/tools/expand-yaml-anchors", "src/tools/jsondocck", "src/tools/html-checker", - "src/tools/bump-stage0", -@@ -105,25 +95,9 @@ +- "src/tools/bump-stage0", + "src/tools/lld-wrapper", + ] + +@@ -105,25 +94,9 @@ debug = 0 # Only use debuginfo=1 to further reduce compile times. bootstrap.debug = 1 @@ -65,9 +69,11 @@ # See comments in `library/rustc-std-workspace-core/README.md` for what's going on # here +diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py +index 7c36bb2..3f90012 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py -@@ -982,10 +982,6 @@ +@@ -1024,10 +1024,6 @@ class RustBuild(object): os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] for _ in range(0, self.verbose): args.append("--verbose") @@ -78,9 +84,11 @@ run(args, env=env, verbose=self.verbose) def build_triple(self): +diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs +index 6ccf8b1..3bf0523 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs -@@ -481,7 +481,6 @@ +@@ -480,7 +480,6 @@ impl<'a> Builder<'a> { doc::RustdocBook, doc::RustByExample, doc::RustcBook, @@ -88,7 +96,7 @@ doc::Clippy, doc::EmbeddedBook, doc::EditionGuide, -@@ -506,7 +505,6 @@ +@@ -505,7 +504,6 @@ impl<'a> Builder<'a> { dist::Miri, dist::LlvmTools, dist::RustDev, @@ -96,7 +104,7 @@ dist::BuildManifest, dist::ReproducibleArtifacts, ), -@@ -1522,10 +1520,7 @@ +@@ -1532,10 +1530,7 @@ impl<'a> Builder<'a> { } } @@ -108,9 +116,11 @@ cargo.arg("--frozen"); } +diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs +index f0f31c4..01d9b84 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs -@@ -76,7 +76,6 @@ +@@ -76,7 +76,6 @@ macro_rules! book { // FIXME: Make checking for a submodule automatic somehow (maybe by having a list of all submodules // and checking against it?). book!( @@ -118,9 +128,11 @@ EditionGuide, "src/doc/edition-guide", "edition-guide", submodule; EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule; Nomicon, "src/doc/nomicon", "nomicon", submodule; +diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs +index cb1b0eb..74af81d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs -@@ -1833,17 +1833,7 @@ +@@ -1833,17 +1833,7 @@ impl Step for RustcGuide { } fn run(self, builder: &Builder<'_>) { @@ -139,9 +151,11 @@ } } +diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml +index 8661a86..e94b7e2 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml -@@ -34,11 +34,6 @@ +@@ -34,11 +34,6 @@ regex = "1.5" # This is used by the `collect-metadata` alias. filetime = "0.2" @@ -153,9 +167,25 @@ # UI test dependencies clippy_utils = { path = "clippy_utils" } derive-new = "0.5" +diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml +index 8d9c4a7..f92b1dc 100644 +--- a/src/tools/rustfmt/Cargo.toml ++++ b/src/tools/rustfmt/Cargo.toml +@@ -58,9 +58,4 @@ lazy_static = "1.0.0" + anyhow = "1.0" + thiserror = "1.0" + +-# A noop dependency that changes in the Rust repository, it's a bit of a hack. +-# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` +-# for more information. +-rustc-workspace-hack = "1.0.0" +- + # Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. +diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs +index 4c28655..0510e71 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs -@@ -272,8 +272,8 @@ +@@ -274,8 +274,8 @@ const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[ // These two crates take quite a long time to build, so don't allow two versions of them // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times // under control. @@ -166,15 +196,3 @@ ]; /// Dependency checks. ---- a/src/tools/rustfmt/Cargo.toml -+++ b/src/tools/rustfmt/Cargo.toml -@@ -58,9 +58,4 @@ - anyhow = "1.0" - thiserror = "1.0" - --# A noop dependency that changes in the Rust repository, it's a bit of a hack. --# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` --# for more information. --rustc-workspace-hack = "1.0.0" -- - # Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch 2022-06-01 08:48:08.000000000 +0000 @@ -14,10 +14,10 @@ 7 files changed, 24 insertions(+), 202 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs -index 94ebbb3..6617bec 100644 +index 94e82e3..ad8dfe5 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs -@@ -193,7 +193,15 @@ impl Checker { +@@ -195,7 +195,15 @@ impl Checker { fn check(&mut self, file: &Path, report: &mut Report) { let (pretty_path, entry) = self.load_file(file, report); let source = match entry { @@ -34,7 +34,7 @@ FileEntry::Dir => unreachable!("never with `check` path"), FileEntry::OtherFile => return, FileEntry::Redirect { .. } => return, -@@ -258,6 +266,12 @@ impl Checker { +@@ -260,6 +268,12 @@ impl Checker { let (target_pretty_path, target_entry) = self.load_file(&path, report); let (target_source, target_ids) = match target_entry { FileEntry::Missing => { @@ -65,7 +65,7 @@ } diff --git a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs -index 02b7da4..0140218 100644 +index e8da5b4..a0507fd 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs @@ -3,7 +3,7 @@ use crate::config::{BookConfig, Config, HtmlConfig, Playground, RustEdition}; @@ -85,9 +85,9 @@ use crate::utils::fs::get_404_output_file; use handlebars::Handlebars; -@@ -228,80 +229,13 @@ impl HtmlHandlebars { +@@ -225,80 +226,13 @@ impl HtmlHandlebars { if let Some(contents) = &theme.favicon_svg { - write_file(destination, "favicon.svg", &contents)?; + write_file(destination, "favicon.svg", contents)?; } - write_file(destination, "highlight.css", &theme.highlight_css)?; write_file(destination, "tomorrow-night.css", &theme.tomorrow_night_css)?; @@ -172,7 +172,7 @@ Ok(()) } diff --git a/vendor/mdbook/src/renderer/html_handlebars/search.rs b/vendor/mdbook/src/renderer/html_handlebars/search.rs -index e9da219..da9ee97 100644 +index 39b5980..7ea49c5 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/search.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/search.rs @@ -34,8 +34,6 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0004-cc-psm-rebuild-wasm32.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0004-cc-psm-rebuild-wasm32.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0004-cc-psm-rebuild-wasm32.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0004-cc-psm-rebuild-wasm32.patch 2022-06-01 08:48:08.000000000 +0000 @@ -8,10 +8,10 @@ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs -index 2de2457..916144d 100644 +index a268fbe..b13944c 100644 --- a/vendor/cc/src/lib.rs +++ b/vendor/cc/src/lib.rs -@@ -2173,7 +2173,7 @@ impl Build { +@@ -2193,7 +2193,7 @@ impl Build { || target == "wasm32-unknown-wasi" || target == "wasm32-unknown-unknown" { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0005-clippy-feature-sync.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0005-clippy-feature-sync.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0005-clippy-feature-sync.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0005-clippy-feature-sync.patch 2022-06-01 08:48:08.000000000 +0000 @@ -5,32 +5,36 @@ enable features needed by rustfmt to make build system happy and speedup build. this is what rustc_workspace_hack does in the upstream build. --- - src/tools/clippy/Cargo.toml | 3 +-- + src/tools/clippy/Cargo.toml | 3 ++- src/tools/rustfmt/Cargo.toml | 2 +- - 2 files changed, 2 insertions(+), 3 deletions(-) + 2 files changed, 3 insertions(+), 2 deletions(-) +diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml +index e94b7e2..6ab5209 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml -@@ -30,7 +30,6 @@ - cargo_metadata = "0.14" - compiletest_rs = { version = "0.7.1", features = ["tmp"] } - tester = "0.9" --regex = "1.5" - # This is used by the `collect-metadata` alias. - filetime = "0.2" +@@ -25,6 +25,7 @@ clippy_lints = { version = "0.1", path = "clippy_lints" } + semver = "1.0" + rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } + tempfile = { version = "3.2", optional = true } ++memchr = { version = "2.4", default_features = false, features = ["use_std"] } -@@ -41,7 +40,7 @@ + [dev-dependencies] + cargo_metadata = "0.14" +@@ -41,7 +42,7 @@ if_chain = "1.0" itertools = "0.10" quote = "1.0" serde = { version = "1.0", features = ["derive"] } -syn = { version = "1.0", features = ["full"] } +syn = { version = "1.0", features = ["full", "visit"] } + parking_lot = "0.11.2" [build-dependencies] - rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } +diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml +index f92b1dc..9e3b2a7 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml -@@ -36,7 +36,7 @@ +@@ -36,7 +36,7 @@ generic-simd = ["bytecount/generic-simd"] itertools = "0.9" toml = "0.5" serde = { version = "1.0", features = ["derive"] } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0007-remove-curl-openssl-dep.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0007-remove-curl-openssl-dep.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-0007-remove-curl-openssl-dep.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-0007-remove-curl-openssl-dep.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ ---- a/src/tools/rustc-workspace-hack/Cargo.toml -+++ b/src/tools/rustc-workspace-hack/Cargo.toml -@@ -72,7 +72,6 @@ - [dependencies] - bstr = { version = "0.2.13", features = ["default"] } - byteorder = { version = "1", features = ['default', 'std'] } --curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } - crossbeam-utils = { version = "0.8.0", features = ["nightly"] } - libc = { version = "0.2.79", features = ["align"] } - # Ensure default features of libz-sys, which are disabled in some scenarios. -@@ -85,9 +84,3 @@ - smallvec = { version = "1.6.1", features = ['union', 'may_dangle'] } - syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'visit-mut'] } - url = { version = "2.0", features = ['serde'] } -- --[target.'cfg(not(windows))'.dependencies] --openssl = { version = "0.10.35", optional = true } -- --[features] --all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx'] ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -25,7 +25,6 @@ - "src/tools/unicode-table-generator", - "src/tools/jsondocck", - "src/tools/html-checker", -- "src/tools/bump-stage0", - "src/tools/lld-wrapper", - ] - diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-cargo-doc-paths.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-cargo-doc-paths.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-cargo-doc-paths.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-cargo-doc-paths.patch 2022-06-01 08:48:08.000000000 +0000 @@ -2,9 +2,11 @@ We package cargo docs in a slightly different location; also tweak linkchecker to not fail these links. ---- a/src/tools/linkchecker/main.rs -+++ b/src/tools/linkchecker/main.rs -@@ -274,6 +274,12 @@ +Index: rust/src/tools/linkchecker/main.rs +=================================================================== +--- rust.orig/src/tools/linkchecker/main.rs ++++ rust/src/tools/linkchecker/main.rs +@@ -272,6 +272,12 @@ impl Checker { return; } } @@ -17,9 +19,11 @@ if is_exception(file, &target_pretty_path) { report.links_ignored_exception += 1; } else { ---- a/src/doc/index.md -+++ b/src/doc/index.md -@@ -87,7 +87,7 @@ +Index: rust/src/doc/index.md +=================================================================== +--- rust.orig/src/doc/index.md ++++ rust/src/doc/index.md +@@ -87,7 +87,7 @@ accomplishing various tasks. ## The Cargo Book @@ -28,9 +32,11 @@ ## The Rustdoc Book ---- a/src/doc/reference/src/conditional-compilation.md -+++ b/src/doc/reference/src/conditional-compilation.md -@@ -335,6 +335,6 @@ +Index: rust/src/doc/reference/src/conditional-compilation.md +=================================================================== +--- rust.orig/src/doc/reference/src/conditional-compilation.md ++++ rust/src/doc/reference/src/conditional-compilation.md +@@ -335,6 +335,6 @@ println!("I'm running on a {} machine!", [`target_feature` attribute]: attributes/codegen.md#the-target_feature-attribute [attribute]: attributes.md [attributes]: attributes.md @@ -38,9 +44,11 @@ +[cargo-feature]: ../../cargo-doc/doc/reference/features.html [crate type]: linkage.md [static C runtime]: linkage.md#static-and-dynamic-c-runtimes ---- a/src/doc/reference/src/introduction.md -+++ b/src/doc/reference/src/introduction.md -@@ -135,8 +135,8 @@ +Index: rust/src/doc/reference/src/introduction.md +=================================================================== +--- rust.orig/src/doc/reference/src/introduction.md ++++ rust/src/doc/reference/src/introduction.md +@@ -135,8 +135,8 @@ We also want the reference to be as norm [the Rust Reference repository]: https://github.com/rust-lang/reference/ [Unstable Book]: https://doc.rust-lang.org/nightly/unstable-book/ [_Expression_]: expressions.md @@ -51,9 +59,11 @@ [expressions chapter]: expressions.html [file an issue]: https://github.com/rust-lang/reference/issues [lifetime of temporaries]: expressions.html#temporaries ---- a/src/doc/reference/src/linkage.md -+++ b/src/doc/reference/src/linkage.md -@@ -201,7 +201,7 @@ +Index: rust/src/doc/reference/src/linkage.md +=================================================================== +--- rust.orig/src/doc/reference/src/linkage.md ++++ rust/src/doc/reference/src/linkage.md +@@ -201,7 +201,7 @@ fn main() { } ``` @@ -62,9 +72,11 @@ To use this feature locally, you typically will use the `RUSTFLAGS` environment variable to specify flags to the compiler through Cargo. For example to compile ---- a/src/doc/reference/src/procedural-macros.md -+++ b/src/doc/reference/src/procedural-macros.md -@@ -272,7 +272,7 @@ +Index: rust/src/doc/reference/src/procedural-macros.md +=================================================================== +--- rust.orig/src/doc/reference/src/procedural-macros.md ++++ rust/src/doc/reference/src/procedural-macros.md +@@ -272,7 +272,7 @@ fn invoke4() {} ``` [Attribute macros]: #attribute-macros @@ -73,9 +85,11 @@ [Derive macros]: #derive-macros [Function-like macros]: #function-like-procedural-macros [`TokenStream`]: ../proc_macro/struct.TokenStream.html ---- a/src/doc/rustc/src/tests/index.md -+++ b/src/doc/rustc/src/tests/index.md -@@ -300,7 +300,7 @@ +Index: rust/src/doc/rustc/src/tests/index.md +=================================================================== +--- rust.orig/src/doc/rustc/src/tests/index.md ++++ rust/src/doc/rustc/src/tests/index.md +@@ -300,7 +300,7 @@ Experimental support for using custom te [`--test` option]: ../command-line-arguments.md#option-test [`-Z panic-abort-tests`]: https://github.com/rust-lang/rust/issues/67650 [`available_parallelism`]: ../../std/thread/fn.available_parallelism.html @@ -84,7 +98,7 @@ [`libtest`]: ../../test/index.html [`main` function]: ../../reference/crates-and-source-files.html#main-functions [`Result`]: ../../std/result/index.html -@@ -309,7 +309,7 @@ +@@ -309,7 +309,7 @@ Experimental support for using custom te [attribute-should_panic]: ../../reference/attributes/testing.html#the-should_panic-attribute [attribute-test]: ../../reference/attributes/testing.html#the-test-attribute [bench-docs]: ../../unstable-book/library-features/test.html @@ -93,9 +107,11 @@ [crate type]: ../../reference/linkage.html [custom_test_frameworks documentation]: ../../unstable-book/language-features/custom-test-frameworks.html [nightly channel]: ../../book/appendix-07-nightly-rust.html ---- a/src/doc/rustc/src/what-is-rustc.md -+++ b/src/doc/rustc/src/what-is-rustc.md -@@ -5,7 +5,7 @@ +Index: rust/src/doc/rustc/src/what-is-rustc.md +=================================================================== +--- rust.orig/src/doc/rustc/src/what-is-rustc.md ++++ rust/src/doc/rustc/src/what-is-rustc.md +@@ -5,7 +5,7 @@ language, provided by the project itself produce binary code, either as a library or executable. Most Rust programmers don't invoke `rustc` directly, but instead do it through @@ -104,9 +120,11 @@ want to see how Cargo calls `rustc`, you can ```bash ---- a/src/doc/edition-guide/book.toml -+++ b/src/doc/edition-guide/book.toml -@@ -53,15 +53,15 @@ +Index: rust/src/doc/edition-guide/book.toml +=================================================================== +--- rust.orig/src/doc/edition-guide/book.toml ++++ rust/src/doc/edition-guide/book.toml +@@ -53,15 +53,15 @@ git-repository-url = "https://github.com "/rust-2018/the-compiler/incremental-compilation-for-faster-compiles.html" = "https://blog.rust-lang.org/2018/02/15/Rust-1.24.html#incremental-compilation" "/rust-2018/the-compiler/an-attribute-for-deprecation.html" = "../../../reference/attributes/diagnostics.html#the-deprecated-attribute" "/rust-2018/rustup-for-managing-rust-versions.html" = "https://rust-lang.github.io/rustup/" @@ -130,15 +148,17 @@ "/rust-2018/cargo-and-crates-io/crates-io-disallows-wildcard-dependencies.html" = "https://blog.rust-lang.org/2016/01/21/Rust-1.6.html#cratesio-disallows-wildcards" "/rust-2018/documentation/index.html" = "../../../index.html" "/rust-2018/documentation/new-editions-of-the-book.html" = "../../../book/index.html" -@@ -93,4 +93,4 @@ +@@ -93,4 +93,4 @@ git-repository-url = "https://github.com "/rust-next/future.html" = "../../std/future/trait.Future.html" "/rust-next/alloc.html" = "https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-alloc-crate-is-stable" "/rust-next/maybe-uninit.html" = "https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#maybeuninitt-instead-of-memuninitialized" -"/rust-next/cargo-vendor.html" = "../../cargo/commands/cargo-vendor.html" +"/rust-next/cargo-vendor.html" = "../../../cargo-doc/doc/commands/cargo-vendor.html" ---- a/src/doc/edition-guide/src/editions/advanced-migrations.md -+++ b/src/doc/edition-guide/src/editions/advanced-migrations.md -@@ -186,18 +186,18 @@ +Index: rust/src/doc/edition-guide/src/editions/advanced-migrations.md +=================================================================== +--- rust.orig/src/doc/edition-guide/src/editions/advanced-migrations.md ++++ rust/src/doc/edition-guide/src/editions/advanced-migrations.md +@@ -186,18 +186,18 @@ Afterwards, the line with `extern crate We're now more idiomatic, and we didn't have to fix our code manually! @@ -164,9 +184,11 @@ [conditional compilation]: ../../reference/conditional-compilation.html [documentation tests]: ../../rustdoc/documentation-tests.html [JSON messages]: ../../rustc/json.html ---- a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md -+++ b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md -@@ -83,7 +83,7 @@ +Index: rust/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +=================================================================== +--- rust.orig/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md ++++ rust/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +@@ -83,7 +83,7 @@ If new warnings are issued, you may want Congrats! Your code is now valid in both Rust 2015 and Rust 2018! @@ -176,9 +198,11 @@ +[`cargo test`]: ../../../cargo-doc/doc/commands/cargo-test.html [Advanced migration strategies]: advanced-migrations.md [nightly channel]: ../../book/appendix-07-nightly-rust.html ---- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md -+++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md -@@ -21,11 +21,11 @@ +Index: rust/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +=================================================================== +--- rust.orig/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md ++++ rust/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +@@ -21,11 +21,11 @@ The new feature resolver no longer merge crates that are depended on in multiple ways. See [the announcement of Rust 1.51][5] for details. @@ -194,7 +218,7 @@ ## Migration -@@ -176,4 +176,4 @@ +@@ -176,4 +176,4 @@ This snippet of output shows that the pr Then, `bar` depends on `bstr` as a build-dependency with the "default" feature. We can further see that `bstr`'s "default" feature enables "unicode" (among other features). diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-custom-debuginfo-path.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-custom-debuginfo-path.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-custom-debuginfo-path.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-custom-debuginfo-path.patch 2022-06-01 08:48:08.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs -@@ -824,10 +824,9 @@ +@@ -933,10 +933,9 @@ impl Build { match which { GitRepo::Rustc => { diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-disable-git.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-disable-git.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-disable-git.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-disable-git.patch 2022-06-01 08:48:08.000000000 +0000 @@ -4,7 +4,7 @@ --- --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs -@@ -915,7 +915,10 @@ +@@ -918,7 +918,10 @@ impl Step for PlainSourceTarball { } // If we're building from git sources, we need to vendor a complete distribution. diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-old-cargo-compat.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-old-cargo-compat.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-old-cargo-compat.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-old-cargo-compat.patch 2022-06-01 08:48:08.000000000 +0000 @@ -12,7 +12,7 @@ --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs -@@ -443,7 +443,6 @@ +@@ -443,7 +443,6 @@ impl Step for Std { cargo .arg("-p") .arg(package) @@ -20,7 +20,7 @@ .arg("--") .arg("--markdown-css") .arg("rust.css") -@@ -589,7 +588,6 @@ +@@ -589,7 +588,6 @@ impl Step for Rustc { cargo.rustdocflag("--generate-link-to-definition"); compile::rustc_cargo(builder, &mut cargo, target); cargo.arg("-Zunstable-options"); @@ -28,7 +28,7 @@ // Only include compiler crates, no dependencies of those, such as `libc`. // Do link to dependencies on `docs.rs` however using `rustdoc-map`. -@@ -722,7 +720,6 @@ +@@ -722,7 +720,6 @@ macro_rules! tool_doc { &[], ); diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-read-beta-version-from-file.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-read-beta-version-from-file.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-read-beta-version-from-file.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-read-beta-version-from-file.patch 2022-06-01 08:48:08.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs -@@ -1031,15 +1031,13 @@ +@@ -1161,15 +1161,13 @@ impl Build { return s; } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-rustflags.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-rustflags.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-rustflags.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-rustflags.patch 2022-06-01 08:48:08.000000000 +0000 @@ -1,7 +1,7 @@ --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs -@@ -993,6 +993,18 @@ - rustflags.arg("-Zsymbol-mangling-version=legacy"); +@@ -1003,6 +1003,18 @@ impl<'a> Builder<'a> { + } } + // Debian-specific stuff here diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-use-local-css.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-use-local-css.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-use-local-css.patch 2022-04-28 10:40:50.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-bootstrap-use-local-css.patch 2022-06-01 08:48:08.000000000 +0000 @@ -1,6 +1,6 @@ --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs -@@ -375,6 +375,10 @@ +@@ -375,6 +375,10 @@ impl Step for Standalone { .arg(&builder.src.join("src/doc/index.md")) .arg("--markdown-playground-url") .arg("https://play.rust-lang.org/") @@ -11,7 +11,7 @@ .arg("-o") .arg(&out) .arg(&path); -@@ -383,17 +387,6 @@ +@@ -383,17 +387,6 @@ impl Step for Standalone { cmd.arg("--disable-minification"); } diff -Nru rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-remove-arm-privacy-breaches.patch rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-remove-arm-privacy-breaches.patch --- rustc-1.58.1+dfsg1~ubuntu1~llvm/debian/patches/d-remove-arm-privacy-breaches.patch 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.59.0+dfsg1~ubuntu1~llvm/debian/patches/d-remove-arm-privacy-breaches.patch 2022-06-01 08:48:08.000000000 +0000 @@ -0,0 +1,186 @@ +Index: rust/library/stdarch/crates/stdarch-verify/arm-intrinsics.html +=================================================================== +--- rust.orig/library/stdarch/crates/stdarch-verify/arm-intrinsics.html ++++ rust/library/stdarch/crates/stdarch-verify/arm-intrinsics.html +@@ -20,17 +20,12 @@ + + + +- +- +- + + + + + +- + +- + + + +@@ -41,64 +36,14 @@ + + + +- +- + + + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- + + + + + +- +- +- + +