diff -Nru rustc-1.52.1+dfsg1+llvm/Cargo.lock rustc-1.53.0+dfsg1+llvm/Cargo.lock --- rustc-1.52.1+dfsg1+llvm/Cargo.lock 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/Cargo.lock 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "addr2line" version = "0.14.0" @@ -58,18 +60,12 @@ [[package]] name = "annotate-snippets" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" -dependencies = [ - "ansi_term 0.11.0", -] - -[[package]] -name = "annotate-snippets" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" +dependencies = [ + "yansi-term", +] [[package]] name = "ansi_term" @@ -102,16 +98,10 @@ checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" [[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] name = "arrayvec" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" [[package]] name = "atty" @@ -131,12 +121,6 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - -[[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -152,17 +136,6 @@ ] [[package]] -name = "blake2b_simd" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - -[[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -252,11 +225,11 @@ [[package]] name = "bytecount" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" +checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" dependencies = [ - "packed_simd", + "packed_simd_2", ] [[package]] @@ -279,7 +252,7 @@ [[package]] name = "cargo" -version = "0.53.0" +version = "0.54.0" dependencies = [ "anyhow", "atty", @@ -287,11 +260,10 @@ "cargo-platform", "cargo-test-macro", "cargo-test-support", + "cargo-util", "clap", - "core-foundation", "crates-io", - "crossbeam-utils 0.8.0", - "crypto-hash", + "crossbeam-utils 0.8.3", "curl", "curl-sys", "env_logger 0.8.1", @@ -313,7 +285,6 @@ "libgit2-sys", "log", "memchr", - "miow 0.3.6", "num_cpus", "opener", "openssl", @@ -322,7 +293,6 @@ "rand 0.8.3", "rustc-workspace-hack", "rustfix", - "same-file", "semver 0.10.0", "serde", "serde_ignored", @@ -396,8 +366,9 @@ name = "cargo-test-support" version = "0.1.0" dependencies = [ - "cargo", + "anyhow", "cargo-test-macro", + "cargo-util", "filetime", "flate2", "git2", @@ -411,6 +382,26 @@ ] [[package]] +name = "cargo-util" +version = "0.1.0" +dependencies = [ + "anyhow", + "core-foundation", + "crypto-hash", + "filetime", + "hex 0.4.2", + "jobserver", + "libc", + "log", + "miow 0.3.6", + "same-file", + "shell-escape", + "tempfile", + "walkdir", + "winapi 0.3.9", +] + +[[package]] name = "cargo_metadata" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -557,20 +548,22 @@ [[package]] name = "clippy" -version = "0.1.52" +version = "0.1.53" dependencies = [ "cargo_metadata 0.12.0", "clippy-mini-macro-test", "clippy_lints", - "compiletest_rs 0.6.0", + "compiletest_rs", "derive-new", + "quote", "regex", "rustc-workspace-hack", "rustc_tools_util 0.2.0", "semver 0.11.0", "serde", + "syn", "tempfile", - "tester 0.9.0", + "tester", ] [[package]] @@ -578,8 +571,21 @@ version = "0.2.0" [[package]] +name = "clippy_dev" +version = "0.0.1" +dependencies = [ + "bytecount", + "clap", + "itertools 0.9.0", + "opener", + "regex", + "shell-escape", + "walkdir", +] + +[[package]] name = "clippy_lints" -version = "0.1.52" +version = "0.1.53" dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", @@ -587,13 +593,10 @@ "itertools 0.9.0", "pulldown-cmark 0.8.0", "quine-mc_cluskey", - "quote", "regex-syntax", "rustc-semver", "semver 0.11.0", "serde", - "smallvec 1.6.1", - "syn", "toml", "unicode-normalization", "url 2.1.1", @@ -601,28 +604,17 @@ [[package]] name = "clippy_utils" -version = "0.1.52" +version = "0.1.53" dependencies = [ "if_chain", "itertools 0.9.0", "regex-syntax", "rustc-semver", "serde", - "smallvec 1.6.1", - "toml", "unicode-normalization", ] [[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags", -] - -[[package]] name = "cmake" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -694,28 +686,6 @@ [[package]] name = "compiletest_rs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f737835bfbbe29ed1ff82d5137520338d7ed5bf1a1d4b9c1c7c58bb45b8fa29" -dependencies = [ - "diff", - "filetime", - "getopts", - "libc", - "log", - "miow 0.3.6", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tempfile", - "tester 0.7.0", - "winapi 0.3.9", -] - -[[package]] -name = "compiletest_rs" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb" @@ -733,23 +703,11 @@ "serde_derive", "serde_json", "tempfile", - "tester 0.9.0", + "tester", "winapi 0.3.9", ] [[package]] -name = "const_fn" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] name = "core" version = "0.0.0" dependencies = [ @@ -810,7 +768,7 @@ checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.3", ] [[package]] @@ -863,13 +821,12 @@ [[package]] name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", "cfg-if 1.0.0", - "const_fn", "lazy_static", ] @@ -996,9 +953,9 @@ [[package]] name = "directories" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fed639d60b58d0f53498ab13d26f621fd77569cc6edb031f4cc36a2ad9da0f" +checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" dependencies = [ "dirs-sys", ] @@ -1025,12 +982,12 @@ [[package]] name = "dirs-sys" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", - "redox_users 0.3.4", + "redox_users", "winapi 0.3.9", ] @@ -1041,7 +998,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users 0.4.0", + "redox_users", "winapi 0.3.9", ] @@ -1087,6 +1044,26 @@ ] [[package]] +name = "enum-iterator" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "env_logger" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1220,6 +1197,12 @@ ] [[package]] +name = "fs-err" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431" + +[[package]] name = "fs_extra" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1227,12 +1210,9 @@ [[package]] name = "fst" -version = "0.3.5" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927fb434ff9f0115b215dc0efd2e4fbdd7448522a92a1aa37c77d6a2f8f1ebd6" -dependencies = [ - "byteorder", -] +checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f" [[package]] name = "fuchsia-zircon" @@ -1426,6 +1406,18 @@ ] [[package]] +name = "getset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1622,11 +1614,11 @@ [[package]] name = "ignore" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22dcbf2a4a289528dbef21686354904e1c694ac642610a9bff9e7df730d9ec72" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" dependencies = [ - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "globset", "lazy_static", "log", @@ -1719,35 +1711,25 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] -name = "jemalloc-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" -dependencies = [ - "cc", - "fs_extra", - "libc", -] - -[[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" dependencies = [ "libc", ] [[package]] name = "json" -version = "0.11.15" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c245af8786f6ac35f95ca14feca9119e71339aaab41e878e7cdd655c97e9e5" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" [[package]] name = "jsondocck" version = "0.1.0" dependencies = [ + "fs-err", "getopts", "jsonpath_lib", "lazy_static", @@ -1895,9 +1877,9 @@ [[package]] name = "libc" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" dependencies = [ "rustc-std-workspace-core", ] @@ -1917,6 +1899,12 @@ ] [[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + +[[package]] name = "libnghttp2-sys" version = "0.1.4+1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2145,7 +2133,7 @@ "parking_lot", "perf-event-open-sys", "rustc-hash", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -2294,17 +2282,17 @@ version = "0.1.0" dependencies = [ "colored", - "compiletest_rs 0.5.0", - "env_logger 0.7.1", + "compiletest_rs", + "env_logger 0.8.1", "getrandom 0.2.0", "hex 0.4.2", "libc", "log", - "rand 0.7.3", + "rand 0.8.3", "rustc-workspace-hack", "rustc_version", "shell-escape", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -2459,18 +2447,20 @@ ] [[package]] -name = "packed_simd" -version = "0.3.3" +name = "packed_simd_2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" +checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17" dependencies = [ "cfg-if 0.1.10", + "libm", ] [[package]] name = "panic_abort" version = "0.0.0" dependencies = [ + "alloc", "cfg-if 0.1.10", "compiler_builtins", "core", @@ -2507,9 +2497,9 @@ [[package]] name = "parking_lot" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", "lock_api", @@ -2518,16 +2508,15 @@ [[package]] name = "parking_lot_core" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", + "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.1.57", - "smallvec 1.6.1", + "redox_syscall 0.2.5", + "smallvec", "winapi 0.3.9", ] @@ -2765,9 +2754,9 @@ [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid", ] @@ -2855,9 +2844,9 @@ [[package]] name = "racer" -version = "2.1.44" +version = "2.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7972a124e2b24dce35eb19f81eced829faec0e8227a7d744bbb1089934d05399" +checksum = "e7cbda48a9124ed2e83766d2c15e3725710d344abca35fad8cf52341a55883b1" dependencies = [ "bitflags", "clap", @@ -3027,17 +3016,6 @@ [[package]] name = "redox_users" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" -dependencies = [ - "getrandom 0.1.14", - "redox_syscall 0.1.57", - "rust-argon2", -] - -[[package]] -name = "redox_users" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" @@ -3097,6 +3075,7 @@ dependencies = [ "anyhow", "cargo", + "cargo-util", "cargo_metadata 0.8.2", "clippy_lints", "crossbeam-channel", @@ -3105,7 +3084,7 @@ "futures 0.3.12", "heck", "home", - "itertools 0.8.2", + "itertools 0.9.0", "jsonrpc-core", "lazy_static", "log", @@ -3140,14 +3119,14 @@ [[package]] name = "rls-analysis" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534032993e1b60e5db934eab2dde54da7afd1e46c3465fddb2b29eb47cb1ed3a" +version = "0.18.2" dependencies = [ "derive-new", + "env_logger 0.7.1", "fst", - "itertools 0.8.2", + "itertools 0.9.0", "json", + "lazy_static", "log", "rls-data", "rls-span", @@ -3212,18 +3191,6 @@ ] [[package]] -name = "rust-argon2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils 0.7.2", -] - -[[package]] name = "rust-demangler" version = "0.0.1" dependencies = [ @@ -3242,18 +3209,19 @@ [[package]] name = "rustc-ap-rustc_arena" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93575affa286089b92c8208aea4e60fe9fdd251a619a09b566d6e4e2cc123212" +checksum = "526610f47139efa440178239553b59ea805ff57a532b4e295c71d2a9b18fd676" dependencies = [ - "smallvec 1.6.1", + "rustc-ap-rustc_data_structures", + "smallvec", ] [[package]] name = "rustc-ap-rustc_ast" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c700f2d3b25aa8d6446dd2936048737b08b2d547bd86e2a70afa9fee4e9c522" +checksum = "cf6a9dda0804a7243b0282e3b75a8cf4654c7a61f033e587751941e1fe39391b" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3262,34 +3230,15 @@ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "smallvec 1.6.1", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_passes" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e01f63e5259ee397bbe2e395d34a2e6b6b24f10c184d30fbbee1dcd7117f4f3" -dependencies = [ - "itertools 0.9.0", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", + "smallvec", "tracing", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d644c69c55deb24257cb0cb5261265fe5134f6f545e9062e1c18b07e422c68" +checksum = "82f5019be8b41a58664169fd2f4b1a37fe82705681db394b76419e4e87d40ab1" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -3297,38 +3246,21 @@ ] [[package]] -name = "rustc-ap-rustc_attr" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797fc68816d5396870f04e03d35164f5275d2502403239d4caec7ce063683f41" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", -] - -[[package]] name = "rustc-ap-rustc_data_structures" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d840c4e6198b57982a54543ae604d634c7ceb7107f0c75970b88ebaff077ac5" +checksum = "a701717fb14549331085756b9741ae3b4bf35808489f1887d72c1d0e0fe52b77" dependencies = [ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", "libc", "measureme", + "memmap2", "parking_lot", "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", @@ -3337,7 +3269,7 @@ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.6.1", + "smallvec", "stable_deref_trait", "stacker", "tempfile", @@ -3347,11 +3279,11 @@ [[package]] name = "rustc-ap-rustc_errors" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f2f99bdc828ad417636d9016611dc9047b641fadcb7f533b8b0e9616d81f90b" +checksum = "e3182ce85e8bfc96443475547f2f5aa2b5e67655d9b88721795f36f0ba9e265a" dependencies = [ - "annotate-snippets 0.8.0", + "annotate-snippets", "atty", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_lint_defs", @@ -3366,34 +3298,10 @@ ] [[package]] -name = "rustc-ap-rustc_expand" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27008b4c7ded287bf5cb20b84d6d5a6566329140f2e2bc8f6e68b37a34898595" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_passes", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec 1.6.1", - "tracing", -] - -[[package]] name = "rustc-ap-rustc_feature" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb47b53670f1263ed1389dda932d5b5a6daf98579c1f076c2ee7d7f22709b7c" +checksum = "eed033b93270126ef60963c3ebbd0e026bf53b985172b6366c7b0e7881c9d507" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -3401,21 +3309,21 @@ [[package]] name = "rustc-ap-rustc_fs_util" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdaddc4bae5ffab17037553e172f5014686db600050429aaa60aec14fe780e84" +checksum = "28ee6531986a205101e09fd143d7bf31897388f33b1814d4bcc45fd62211dca6" [[package]] name = "rustc-ap-rustc_graphviz" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d73c72543311e88786f7380a3bfd946395579c1a0c0441a879a97fcdea79130" +checksum = "3398fddc0e23d2db89c036f8952ddf78cadc597f7059752116e69483e164a5b6" [[package]] name = "rustc-ap-rustc_index" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba8d74ed4bad44a5b4264cf2a51ad0bd458ed56caa5bb090e989b8002ec6327" +checksum = "dca4e27eb5b701f6bbd47d8fc9d242378fca3e4107a519a28415c2989c4a3bd3" dependencies = [ "arrayvec", "rustc-ap-rustc_macros", @@ -3424,18 +3332,18 @@ [[package]] name = "rustc-ap-rustc_lexer" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a030d00510966cd31e13dca5e6c1bd40d303a932c54eca40e854188bca8c49e" +checksum = "786bbfe9d4d5264294c1819dbf1497a2480b583d5eda1ca9ae22e12d6661f5df" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_lint_defs" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff95da1b5d979183ef5c285817ba6cc67a1ac11296ef1e87b1b5bbaf57213c" +checksum = "be2f045e2b999c154ec505d5fea69c994b742f3ebd2f552d11a6c81723921e47" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_data_structures", @@ -3448,9 +3356,9 @@ [[package]] name = "rustc-ap-rustc_macros" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3ed7401bf6f5a256d58cd0e1c1e2e77eec25e60a0d7ad75313962edcb4e396" +checksum = "27789cd26d6b9e2fdfa68a262a20664d79ca67d31a3886d40fb88ebf6935869c" dependencies = [ "proc-macro2", "quote", @@ -3460,9 +3368,9 @@ [[package]] name = "rustc-ap-rustc_parse" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609a624baffa3f99847d57d30c96ee6732ce0912f8df4be239b6fd91533910d6" +checksum = "1dc331f4958350679679e619d63a891e8d5d34ef99087068c89aa9e657d52caa" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -3473,26 +3381,26 @@ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc232e2a351d8131c8f1386ce372ee22ef7b1b0b897bbf817a8ce4792029a564" +checksum = "e9a6824a462c4c1a379e911b0faf86d303a54bcf8673d4cc445195085966a4a4" dependencies = [ "indexmap", - "smallvec 1.6.1", + "smallvec", ] [[package]] name = "rustc-ap-rustc_session" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18acf94c820cd0c64ee1cbd811fd1f4d5ba18987c457c88771359b90cb1a12f5" +checksum = "a782a5f6ada0dbe089c6416ad0104f0b8a8bdb4bd26ea95e5fefaec67aed5e8a" dependencies = [ "bitflags", "getopts", @@ -3512,9 +3420,9 @@ [[package]] name = "rustc-ap-rustc_span" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3479f453a38b6a5572938d035fc2b3cb6ec379c57f598b8682b512eb90c7858" +checksum = "a257546cb264b250c7abdb81239bb02f18a274a966211755a3ea89411b122214" dependencies = [ "cfg-if 0.1.10", "md-5", @@ -3532,9 +3440,9 @@ [[package]] name = "rustc-ap-rustc_target" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cacaf829778cf07bb97a9f4604896789de12392175f3743e74a30ed370f1c1" +checksum = "b5a72dd689421bcb5750f3ed0dedf367076e714ef0ba56c02ed391b9a8582862" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3565,9 +3473,10 @@ name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", + "tikv-jemalloc-sys", + "tikv-jemallocator", ] [[package]] @@ -3626,15 +3535,15 @@ version = "1.0.0" dependencies = [ "byteorder", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "libc", "libz-sys", "proc-macro2", "quote", + "rand_core 0.5.1", "serde", "serde_json", - "smallvec 0.6.14", - "smallvec 1.6.1", + "smallvec", "syn", "url 2.1.1", "winapi 0.3.9", @@ -3645,7 +3554,7 @@ version = "0.0.0" dependencies = [ "bitflags", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -3653,7 +3562,7 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -3667,7 +3576,7 @@ "rustc_macros", "rustc_serialize", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3685,7 +3594,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3748,7 +3657,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3777,7 +3686,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "snap", "tracing", ] @@ -3791,7 +3700,6 @@ "itertools 0.9.0", "jobserver", "libc", - "memmap2", "pathdiff", "rustc_apfloat", "rustc_ast", @@ -3820,12 +3728,13 @@ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", "libc", "measureme", + "memmap2", "parking_lot", "rustc-hash", "rustc-rayon", @@ -3834,7 +3743,7 @@ "rustc_index", "rustc_macros", "rustc_serialize", - "smallvec 1.6.1", + "smallvec", "stable_deref_trait", "stacker", "tempfile", @@ -3885,7 +3794,7 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.8.0", + "annotate-snippets", "atty", "rustc_data_structures", "rustc_lint_defs", @@ -3917,7 +3826,7 @@ "rustc_serialize", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3949,7 +3858,7 @@ "rustc_serialize", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4007,7 +3916,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4051,7 +3960,7 @@ "rustc_traits", "rustc_ty_utils", "rustc_typeck", - "smallvec 1.6.1", + "smallvec", "tempfile", "tracing", "winapi 0.3.9", @@ -4125,7 +4034,6 @@ version = "0.0.0" dependencies = [ "libc", - "memmap2", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -4141,7 +4049,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "snap", "stable_deref_trait", "tracing", @@ -4173,7 +4081,7 @@ "rustc_span", "rustc_target", "rustc_type_ir", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4204,7 +4112,7 @@ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4227,7 +4135,7 @@ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4244,7 +4152,7 @@ "rustc_lexer", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", "unicode-normalization", ] @@ -4345,7 +4253,7 @@ "rustc_serialize", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4369,7 +4277,7 @@ "rustc_middle", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4398,7 +4306,7 @@ dependencies = [ "indexmap", "rustc_macros", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -4495,7 +4403,7 @@ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4515,7 +4423,7 @@ "rustc_middle", "rustc_span", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4565,17 +4473,18 @@ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "rustc_ty_utils", + "smallvec", "tracing", ] [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", ] [[package]] @@ -4592,7 +4501,7 @@ "rustdoc-json-types", "serde", "serde_json", - "smallvec 1.6.1", + "smallvec", "tempfile", "tracing", "tracing-subscriber", @@ -4642,9 +4551,9 @@ [[package]] name = "rustfmt-nightly" -version = "1.4.36" +version = "1.4.37" dependencies = [ - "annotate-snippets 0.6.1", + "annotate-snippets", "anyhow", "bytecount", "cargo_metadata 0.8.2", @@ -4658,15 +4567,6 @@ "lazy_static", "log", "regex", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_expand", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", @@ -4793,18 +4693,18 @@ [[package]] name = "serde" -version = "1.0.118" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ "proc-macro2", "quote", @@ -4941,15 +4841,6 @@ [[package]] name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" @@ -5012,11 +4903,23 @@ "profiler_builtins", "rand 0.7.3", "rustc-demangle", + "std_detect", "unwind", "wasi", ] [[package]] +name = "std_detect" +version = "0.1.5" +dependencies = [ + "cfg-if 0.1.10", + "compiler_builtins", + "libc", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] name = "string_cache" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5100,9 +5003,9 @@ [[package]] name = "syn" -version = "1.0.38" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" +checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ "proc-macro2", "quote", @@ -5135,14 +5038,14 @@ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "rand 0.7.3", - "redox_syscall 0.1.57", + "rand 0.8.3", + "redox_syscall 0.2.5", "remove_dir_all", "winapi 0.3.9", ] @@ -5223,17 +5126,6 @@ [[package]] name = "tester" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee72ec31009a42b53de9a6b7d8f462b493ab3b1e4767bda1fcdbb52127f13b6c" -dependencies = [ - "getopts", - "libc", - "term 0.6.1", -] - -[[package]] -name = "tester" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb" @@ -5288,6 +5180,7 @@ version = "0.1.0" dependencies = [ "cargo_metadata 0.11.1", + "crossbeam-utils 0.8.3", "lazy_static", "regex", "walkdir", @@ -5298,6 +5191,27 @@ version = "0.1.0" [[package]] +name = "tikv-jemalloc-sys" +version = "0.4.1+5.2.1-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a26331b05179d4cb505c8d6814a7e18d298972f0a551b0e3cefccff927f86d3" +dependencies = [ + "cc", + "fs_extra", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + +[[package]] name = "time" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5444,7 +5358,7 @@ "serde", "serde_json", "sharded-slab", - "smallvec 1.6.1", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -5644,12 +5558,17 @@ [[package]] name = "vergen" -version = "3.1.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb" +checksum = "dfbc87f9a7a9d61b15d51d1d3547284f67b6b4f1494ce3fc5814c101f35a5183" dependencies = [ - "bitflags", + "anyhow", "chrono", + "enum-iterator", + "getset", + "git2", + "rustversion", + "thiserror", ] [[package]] @@ -5797,3 +5716,12 @@ dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi 0.3.9", +] diff -Nru rustc-1.52.1+dfsg1+llvm/Cargo.toml rustc-1.53.0+dfsg1+llvm/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -7,6 +7,7 @@ "src/rustdoc-json-types", "src/tools/cargotest", "src/tools/clippy", + "src/tools/clippy/clippy_dev", "src/tools/compiletest", "src/tools/error_index_generator", "src/tools/linkchecker", @@ -45,6 +46,8 @@ # not all `Cargo.toml` files are available, so we exclude the `x` binary, # so it can be invoked before the current checkout is set up. "src/tools/x", + # stdarch has its own Cargo workspace + "library/stdarch", ] [profile.release.package.compiler_builtins] @@ -88,6 +91,7 @@ # vendored copy. [patch."https://github.com/rust-lang/cargo"] cargo = { path = "src/tools/cargo" } +cargo-util = { path = "src/tools/cargo/crates/cargo-util" } [patch."https://github.com/rust-lang/rustfmt"] # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -11,12 +11,16 @@ # crate is intended to be used by codegen backends, which may not be in-tree. rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } -[dependencies.jemalloc-sys] -version = '0.3.0' +[dependencies.tikv-jemalloc-sys] +version = '0.4.0' optional = true features = ['unprefixed_malloc_on_supported_platforms'] +[dependencies.tikv-jemallocator] +version = '0.4.0' +optional = true + [features] -jemalloc = ['jemalloc-sys'] +jemalloc = ['tikv-jemalloc-sys', 'tikv-jemallocator'] llvm = ['rustc_driver/llvm'] max_level_info = ['rustc_driver/max_level_info'] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc/src/main.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc/src/main.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc/src/main.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc/src/main.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,16 @@ +// Configure jemalloc as the `global_allocator` when configured. This is +// so that we use the sized deallocation apis jemalloc provides +// (namely `sdallocx`). +// +// 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; + +#[cfg(feature = "tikv-jemalloc-sys")] +use tikv_jemalloc_sys as jemalloc_sys; + fn main() { // Pull in jemalloc when enabled. // @@ -7,7 +20,7 @@ // 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). - #[cfg(feature = "jemalloc-sys")] + #[cfg(feature = "tikv-jemalloc-sys")] { use std::os::raw::{c_int, c_void}; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_apfloat/src/ieee.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_apfloat/src/ieee.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_apfloat/src/ieee.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_apfloat/src/ieee.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2273,6 +2273,7 @@ mod sig { use super::{limbs_for_bits, ExpInt, Limb, Loss, LIMB_BITS}; use core::cmp::Ordering; + use core::iter; use core::mem; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { @@ -2483,7 +2484,7 @@ pub(super) fn add(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_add(b); let (r, overflow2) = r.overflowing_add(c); *a = r; @@ -2497,7 +2498,7 @@ pub(super) fn sub(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_sub(b); let (r, overflow2) = r.overflowing_sub(c); *a = r; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_apfloat/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_apfloat/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_apfloat/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_apfloat/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -33,8 +33,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![no_std] #![forbid(unsafe_code)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #[macro_use] extern crate alloc; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_arena/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_arena/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_arena/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_arena/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -236,26 +236,6 @@ start_ptr } - /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable - /// reference to it. Will panic if passed a zero-sized types. - /// - /// Panics: - /// - /// - Zero-sized types - /// - Zero-length slices - #[inline] - pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] - where - T: Copy, - { - unsafe { - let len = slice.len(); - let start_ptr = self.alloc_raw_slice(len); - slice.as_ptr().copy_to_nonoverlapping(start_ptr, len); - slice::from_raw_parts_mut(start_ptr, len) - } - } - #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { assert!(mem::size_of::() != 0); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/ast_like.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/ast_like.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/ast_like.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/ast_like.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,20 +1,32 @@ use super::ptr::P; +use super::token::Nonterminal; use super::tokenstream::LazyTokenStream; use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; -use super::{AssocItem, Expr, ForeignItem, Item, Local}; +use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt}; use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; use super::{AttrVec, Attribute, Stmt, StmtKind}; +use std::fmt::Debug; + /// An `AstLike` represents an AST node (or some wrapper around /// and AST node) which stores some combination of attributes /// and tokens. -pub trait AstLike: Sized { +pub trait AstLike: Sized + Debug { + /// This is `true` if this `AstLike` might support 'custom' (proc-macro) inner + /// attributes. Attributes like `#![cfg]` and `#![cfg_attr]` are not + /// considered 'custom' attributes + /// + /// If this is `false`, then this `AstLike` definitely does + /// not support 'custom' inner attributes, which enables some optimizations + /// during token collection. + const SUPPORTS_CUSTOM_INNER_ATTRS: bool; fn attrs(&self) -> &[Attribute]; fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)); fn tokens_mut(&mut self) -> Option<&mut Option>; } impl AstLike for P { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS; fn attrs(&self) -> &[Attribute] { (**self).attrs() } @@ -26,6 +38,55 @@ } } +impl AstLike for crate::token::Nonterminal { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + fn attrs(&self) -> &[Attribute] { + match self { + Nonterminal::NtItem(item) => item.attrs(), + Nonterminal::NtStmt(stmt) => stmt.attrs(), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.attrs(), + Nonterminal::NtPat(_) + | Nonterminal::NtTy(_) + | Nonterminal::NtMeta(_) + | Nonterminal::NtPath(_) + | Nonterminal::NtVis(_) + | Nonterminal::NtTT(_) + | Nonterminal::NtBlock(_) + | Nonterminal::NtIdent(..) + | Nonterminal::NtLifetime(_) => &[], + } + } + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + match self { + Nonterminal::NtItem(item) => item.visit_attrs(f), + Nonterminal::NtStmt(stmt) => stmt.visit_attrs(f), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.visit_attrs(f), + Nonterminal::NtPat(_) + | Nonterminal::NtTy(_) + | Nonterminal::NtMeta(_) + | Nonterminal::NtPath(_) + | Nonterminal::NtVis(_) + | Nonterminal::NtTT(_) + | Nonterminal::NtBlock(_) + | Nonterminal::NtIdent(..) + | Nonterminal::NtLifetime(_) => {} + } + } + fn tokens_mut(&mut self) -> Option<&mut Option> { + match self { + Nonterminal::NtItem(item) => item.tokens_mut(), + Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), + Nonterminal::NtPat(pat) => pat.tokens_mut(), + Nonterminal::NtTy(ty) => ty.tokens_mut(), + Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), + Nonterminal::NtPath(path) => path.tokens_mut(), + Nonterminal::NtVis(vis) => vis.tokens_mut(), + _ => panic!("Called tokens_mut on {:?}", self), + } + } +} + fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec)) { crate::mut_visit::visit_clobber(attrs, |attrs| { let mut vec = attrs.into(); @@ -35,6 +96,10 @@ } impl AstLike for StmtKind { + // This might be an `StmtKind::Item`, which contains + // an item that supports inner attrs + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + fn attrs(&self) -> &[Attribute] { match self { StmtKind::Local(local) => local.attrs(), @@ -66,6 +131,8 @@ } impl AstLike for Stmt { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = StmtKind::SUPPORTS_CUSTOM_INNER_ATTRS; + fn attrs(&self) -> &[Attribute] { self.kind.attrs() } @@ -79,6 +146,8 @@ } impl AstLike for Attribute { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &[] } @@ -94,6 +163,8 @@ } impl AstLike for Option { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS; + fn attrs(&self) -> &[Attribute] { self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[]) } @@ -127,8 +198,13 @@ } macro_rules! derive_has_tokens_and_attrs { - ($($ty:path),*) => { $( + ( + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs:literal; + $($ty:path),* + ) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs; + fn attrs(&self) -> &[Attribute] { &self.attrs } @@ -140,6 +216,7 @@ fn tokens_mut(&mut self) -> Option<&mut Option> { Some(&mut self.tokens) } + } )* } } @@ -147,6 +224,8 @@ macro_rules! derive_has_attrs_no_tokens { ($($ty:path),*) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &self.attrs } @@ -165,12 +244,13 @@ macro_rules! derive_has_tokens_no_attrs { ($($ty:path),*) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &[] } fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) {} - fn tokens_mut(&mut self) -> Option<&mut Option> { Some(&mut self.tokens) } @@ -178,10 +258,18 @@ )* } } -// These AST nodes support both inert and active -// attributes, so they also have tokens. +// These ast nodes support both active and inert attributes, +// so they have tokens collected to pass to proc macros +derive_has_tokens_and_attrs! { + // Both `Item` and `AssocItem` can have bodies, which + // can contain inner attributes + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + Item, AssocItem, ForeignItem +} + derive_has_tokens_and_attrs! { - Item, Expr, Local, AssocItem, ForeignItem + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + Local, MacCallStmt, Expr } // These ast nodes only support inert attributes, so they don't diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/ast.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/ast.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/ast.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/ast.rs 2021-06-17 03:53:50.000000000 +0000 @@ -100,6 +100,7 @@ } impl PartialEq for Path { + #[inline] fn eq(&self, symbol: &Symbol) -> bool { self.segments.len() == 1 && { self.segments[0].ident.name == *symbol } } @@ -762,14 +763,6 @@ } impl Mutability { - /// Returns `MutMutable` only if both `self` and `other` are mutable. - pub fn and(self, other: Self) -> Self { - match self { - Mutability::Mut => other, - Mutability::Not => Mutability::Not, - } - } - pub fn invert(self) -> Self { match self { Mutability::Mut => Mutability::Not, @@ -1353,7 +1346,7 @@ Field(P, Ident), /// An indexing operation (e.g., `foo[2]`). Index(P, P), - /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment). + /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assignment). Range(Option>, Option>, RangeLimits), /// An underscore, used in destructuring assignment to ignore a value. Underscore, @@ -1722,13 +1715,6 @@ FloatTy::F64 => sym::f64, } } - - pub fn bit_width(self) -> u64 { - match self { - FloatTy::F32 => 32, - FloatTy::F64 => 64, - } - } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -1764,29 +1750,6 @@ IntTy::I128 => sym::i128, } } - - pub fn bit_width(&self) -> Option { - Some(match *self { - IntTy::Isize => return None, - IntTy::I8 => 8, - IntTy::I16 => 16, - IntTy::I32 => 32, - IntTy::I64 => 64, - IntTy::I128 => 128, - }) - } - - pub fn normalize(&self, target_width: u32) -> Self { - match self { - IntTy::Isize => match target_width { - 16 => IntTy::I16, - 32 => IntTy::I32, - 64 => IntTy::I64, - _ => unreachable!(), - }, - _ => *self, - } - } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] @@ -1822,29 +1785,6 @@ UintTy::U128 => sym::u128, } } - - pub fn bit_width(&self) -> Option { - Some(match *self { - UintTy::Usize => return None, - UintTy::U8 => 8, - UintTy::U16 => 16, - UintTy::U32 => 32, - UintTy::U64 => 64, - UintTy::U128 => 128, - }) - } - - pub fn normalize(&self, target_width: u32) -> Self { - match self { - UintTy::Usize => match target_width { - 16 => UintTy::U16, - 32 => UintTy::U32, - 64 => UintTy::U64, - _ => unreachable!(), - }, - _ => *self, - } - } } /// A constraint on an associated type (e.g., `A = Bar` in `Foo` or @@ -2059,7 +1999,7 @@ out_expr: Option>, }, Const { - expr: P, + anon_const: AnonConst, }, Sym { expr: P, @@ -2215,9 +2155,6 @@ } impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Param::to_self) - } pub fn has_self(&self) -> bool { self.inputs.get(0).map_or(false, Param::is_self) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/attr/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/attr/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/attr/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/attr/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,9 @@ use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Path, PathSegment}; use crate::token::{self, CommentKind, Token}; -use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree, TreeAndSpacing}; +use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing}; +use crate::tokenstream::{LazyTokenStream, TokenStream}; use rustc_index::bit_set::GrowableBitSet; use rustc_span::source_map::BytePos; @@ -100,16 +102,7 @@ self.meta_item().map_or(false, |meta_item| meta_item.is_word()) } - /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - /// Returns `true` if `self` is a `MetaItem` and the meta item is a list. - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } - + /// See [`MetaItem::name_value_literal_span`]. pub fn name_value_literal_span(&self) -> Option { self.meta_item()?.name_value_literal_span() } @@ -165,31 +158,6 @@ false } } - - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } - - /// Indicates if the attribute is a `ValueString`. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - /// This is used in case you want the value span instead of the whole attribute. Example: - /// - /// ```text - /// #[doc(alias = "foo")] - /// ``` - /// - /// In here, it'll return a span for `"foo"`. - pub fn name_value_literal_span(&self) -> Option { - match self.kind { - AttrKind::Normal(ref item, _) => { - item.meta(self.span).and_then(|meta| meta.name_value_literal_span()) - } - AttrKind::DocComment(..) => None, - } - } } impl MetaItem { @@ -236,10 +204,6 @@ self.path == name } - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - /// This is used in case you want the value span instead of the whole attribute. Example: /// /// ```text @@ -306,14 +270,18 @@ } } - pub fn tokens(&self) -> TokenStream { + pub fn tokens(&self) -> AttrAnnotatedTokenStream { match self.kind { AttrKind::Normal(_, ref tokens) => tokens .as_ref() .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self)) .create_token_stream(), - AttrKind::DocComment(comment_kind, data) => TokenStream::from(TokenTree::Token( - Token::new(token::DocComment(comment_kind, self.style, data), self.span), + AttrKind::DocComment(comment_kind, data) => AttrAnnotatedTokenStream::from(( + AttrAnnotatedTokenTree::Token(Token::new( + token::DocComment(comment_kind, self.style, data), + self.span, + )), + Spacing::Alone, )), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/expand/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/expand/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/expand/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/expand/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,3 @@ -//! Definitions shared by macros / syntax extensions and e.g. librustc_middle. +//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`. pub mod allocator; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,13 +10,15 @@ )] #![feature(box_syntax)] #![feature(box_patterns)] -#![feature(const_fn)] // For the `transmute` in `P::new` +#![cfg_attr(bootstrap, feature(const_fn))] // For the `transmute` in `P::new` +#![cfg_attr(not(bootstrap), feature(const_fn_unsize))] // For the `transmute` in `P::new` #![feature(const_fn_transmute)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] +#![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] @@ -58,7 +60,7 @@ /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext: rustc_span::HashStableContext { fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/mut_visit.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/mut_visit.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/mut_visit.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/mut_visit.rs 2021-06-17 03:53:50.000000000 +0000 @@ -631,6 +631,33 @@ } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_attr_annotated_tt(tt: &mut AttrAnnotatedTokenTree, vis: &mut T) { + match tt { + AttrAnnotatedTokenTree::Token(token) => { + visit_token(token, vis); + } + AttrAnnotatedTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => { + vis.visit_span(open); + vis.visit_span(close); + visit_attr_annotated_tts(tts, vis); + } + AttrAnnotatedTokenTree::Attributes(data) => { + for attr in &mut *data.attrs { + match &mut attr.kind { + AttrKind::Normal(_, attr_tokens) => { + visit_lazy_tts(attr_tokens, vis); + } + AttrKind::DocComment(..) => { + vis.visit_span(&mut attr.span); + } + } + } + visit_lazy_tts_opt_mut(Some(&mut data.tokens), vis); + } + } +} + +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. pub fn visit_tt(tt: &mut TokenTree, vis: &mut T) { match tt { TokenTree::Token(token) => { @@ -652,16 +679,30 @@ } } -pub fn visit_lazy_tts(lazy_tts: &mut Option, vis: &mut T) { +pub fn visit_attr_annotated_tts( + AttrAnnotatedTokenStream(tts): &mut AttrAnnotatedTokenStream, + vis: &mut T, +) { + if vis.token_visiting_enabled() && !tts.is_empty() { + let tts = Lrc::make_mut(tts); + visit_vec(tts, |(tree, _is_joint)| visit_attr_annotated_tt(tree, vis)); + } +} + +pub fn visit_lazy_tts_opt_mut(lazy_tts: Option<&mut LazyTokenStream>, vis: &mut T) { if vis.token_visiting_enabled() { - visit_opt(lazy_tts, |lazy_tts| { + if let Some(lazy_tts) = lazy_tts { let mut tts = lazy_tts.create_token_stream(); - visit_tts(&mut tts, vis); + visit_attr_annotated_tts(&mut tts, vis); *lazy_tts = LazyTokenStream::new(tts); - }) + } } } +pub fn visit_lazy_tts(lazy_tts: &mut Option, vis: &mut T) { + visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis); +} + // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. // Applies ident visitor if it's an ident; applies other visits to interpolated nodes. // In practice the ident part is not actually used by specific visitors right now, @@ -1252,7 +1293,6 @@ match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -1265,6 +1305,7 @@ vis.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const), } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/token.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/token.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/token.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/token.rs 2021-06-17 03:53:50.000000000 +0000 @@ -688,16 +688,12 @@ Item, Block, Stmt, - Pat2018 { - /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the - /// edition of the span. This is used for diagnostics. - inferred: bool, - }, - Pat2021 { - /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the + PatParam { + /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the /// edition of the span. This is used for diagnostics. inferred: bool, }, + PatWithOr, Expr, Ty, Ident, @@ -722,12 +718,11 @@ sym::stmt => NonterminalKind::Stmt, sym::pat => match edition() { Edition::Edition2015 | Edition::Edition2018 => { - NonterminalKind::Pat2018 { inferred: true } + NonterminalKind::PatParam { inferred: true } } - Edition::Edition2021 => NonterminalKind::Pat2021 { inferred: true }, + Edition::Edition2021 => NonterminalKind::PatWithOr, }, - sym::pat2018 => NonterminalKind::Pat2018 { inferred: false }, - sym::pat2021 => NonterminalKind::Pat2021 { inferred: false }, + sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, @@ -745,10 +740,8 @@ NonterminalKind::Item => sym::item, NonterminalKind::Block => sym::block, NonterminalKind::Stmt => sym::stmt, - NonterminalKind::Pat2018 { inferred: false } => sym::pat2018, - NonterminalKind::Pat2021 { inferred: false } => sym::pat2021, - NonterminalKind::Pat2018 { inferred: true } - | NonterminalKind::Pat2021 { inferred: true } => sym::pat, + NonterminalKind::PatParam { inferred: false } => sym::pat_param, + NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, NonterminalKind::Expr => sym::expr, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/tokenstream.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/tokenstream.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/tokenstream.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/tokenstream.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,6 +14,7 @@ //! ownership of the original. use crate::token::{self, DelimToken, Token, TokenKind}; +use crate::AttrVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, Lrc}; @@ -89,10 +90,6 @@ } } - pub fn joint(self) -> TokenStream { - TokenStream::new(vec![(self, Spacing::Joint)]) - } - pub fn token(kind: TokenKind, span: Span) -> TokenTree { TokenTree::Token(Token::new(kind, span)) } @@ -127,11 +124,11 @@ } pub trait CreateTokenStream: sync::Send + sync::Sync { - fn create_token_stream(&self) -> TokenStream; + fn create_token_stream(&self) -> AttrAnnotatedTokenStream; } -impl CreateTokenStream for TokenStream { - fn create_token_stream(&self) -> TokenStream { +impl CreateTokenStream for AttrAnnotatedTokenStream { + fn create_token_stream(&self) -> AttrAnnotatedTokenStream { self.clone() } } @@ -147,14 +144,14 @@ LazyTokenStream(Lrc::new(Box::new(inner))) } - pub fn create_token_stream(&self) -> TokenStream { + pub fn create_token_stream(&self) -> AttrAnnotatedTokenStream { self.0.create_token_stream() } } impl fmt::Debug for LazyTokenStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt("LazyTokenStream", f) + write!(f, "LazyTokenStream({:?})", self.create_token_stream()) } } @@ -177,12 +174,151 @@ } } +/// A `AttrAnnotatedTokenStream` is similar to a `TokenStream`, but with extra +/// information about the tokens for attribute targets. This is used +/// during expansion to perform early cfg-expansion, and to process attributes +/// during proc-macro invocations. +#[derive(Clone, Debug, Default, Encodable, Decodable)] +pub struct AttrAnnotatedTokenStream(pub Lrc>); + +/// Like `TokenTree`, but for `AttrAnnotatedTokenStream` +#[derive(Clone, Debug, Encodable, Decodable)] +pub enum AttrAnnotatedTokenTree { + Token(Token), + Delimited(DelimSpan, DelimToken, AttrAnnotatedTokenStream), + /// Stores the attributes for an attribute target, + /// along with the tokens for that attribute target. + /// See `AttributesData` for more information + Attributes(AttributesData), +} + +impl AttrAnnotatedTokenStream { + pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream { + AttrAnnotatedTokenStream(Lrc::new(tokens)) + } + + /// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream + /// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened' + /// back to a `TokenStream` of the form `outer_attr attr_target`. + /// If there are inner attributes, they are inserted into the proper + /// place in the attribute target tokens. + pub fn to_tokenstream(&self) -> TokenStream { + let trees: Vec<_> = self + .0 + .iter() + .flat_map(|tree| match &tree.0 { + AttrAnnotatedTokenTree::Token(inner) => { + smallvec![(TokenTree::Token(inner.clone()), tree.1)].into_iter() + } + AttrAnnotatedTokenTree::Delimited(span, delim, stream) => smallvec![( + TokenTree::Delimited(*span, *delim, stream.to_tokenstream()), + tree.1, + )] + .into_iter(), + AttrAnnotatedTokenTree::Attributes(data) => { + let mut outer_attrs = Vec::new(); + let mut inner_attrs = Vec::new(); + let attrs: Vec<_> = data.attrs.clone().into(); + for attr in attrs { + match attr.style { + crate::AttrStyle::Outer => { + assert!( + inner_attrs.len() == 0, + "Found outer attribute {:?} after inner attrs {:?}", + attr, + inner_attrs + ); + outer_attrs.push(attr); + } + crate::AttrStyle::Inner => { + inner_attrs.push(attr); + } + } + } + + let mut target_tokens: Vec<_> = data + .tokens + .create_token_stream() + .to_tokenstream() + .0 + .iter() + .cloned() + .collect(); + if !inner_attrs.is_empty() { + let mut found = false; + // Check the last two trees (to account for a trailing semi) + for (tree, _) in target_tokens.iter_mut().rev().take(2) { + if let TokenTree::Delimited(span, delim, delim_tokens) = tree { + // Inner attributes are only supported on extern blocks, functions, impls, + // and modules. All of these have their inner attributes placed at + // the beginning of the rightmost outermost braced group: + // e.g. fn foo() { #![my_attr} } + // + // Therefore, we can insert them back into the right location + // without needing to do any extra position tracking. + // + // Note: Outline modules are an exception - they can + // have attributes like `#![my_attr]` at the start of a file. + // Support for custom attributes in this position is not + // properly implemented - we always synthesize fake tokens, + // so we never reach this code. + + let mut builder = TokenStreamBuilder::new(); + for inner_attr in &inner_attrs { + builder.push(inner_attr.tokens().to_tokenstream()); + } + builder.push(delim_tokens.clone()); + *tree = TokenTree::Delimited(*span, *delim, builder.build()); + found = true; + break; + } + } + + assert!( + found, + "Failed to find trailing delimited group in: {:?}", + target_tokens + ); + } + let mut flat: SmallVec<[_; 1]> = SmallVec::new(); + for attr in outer_attrs { + // FIXME: Make this more efficient + flat.extend(attr.tokens().to_tokenstream().0.clone().iter().cloned()); + } + flat.extend(target_tokens); + flat.into_iter() + } + }) + .collect(); + TokenStream::new(trees) + } +} + +/// Stores the tokens for an attribute target, along +/// with its attributes. +/// +/// This is constructed during parsing when we need to capture +/// tokens. +/// +/// For example, `#[cfg(FALSE)] struct Foo {}` would +/// have an `attrs` field containing the `#[cfg(FALSE)]` attr, +/// and a `tokens` field storing the (unparesd) tokens `struct Foo {}` +#[derive(Clone, Debug, Encodable, Decodable)] +pub struct AttributesData { + /// Attributes, both outer and inner. + /// These are stored in the original order that they were parsed in. + pub attrs: AttrVec, + /// The underlying tokens for the attribute target that `attrs` + /// are applied to + pub tokens: LazyTokenStream, +} + /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. /// /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for -/// backwards compatability. +/// backwards compatibility. #[derive(Clone, Debug, Default, Encodable, Decodable)] pub struct TokenStream(pub(crate) Lrc>); @@ -239,6 +375,12 @@ } } +impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream { + fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream { + AttrAnnotatedTokenStream::new(vec![(tree, spacing)]) + } +} + impl From for TokenStream { fn from(tree: TokenTree) -> TokenStream { TokenStream::new(vec![(tree, Spacing::Alone)]) @@ -278,14 +420,6 @@ self.0.len() } - pub fn span(&self) -> Option { - match &**self.0 { - [] => None, - [(tt, _)] => Some(tt.span()), - [(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())), - } - } - pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { match streams.len() { 0 => TokenStream::default(), @@ -325,10 +459,6 @@ } } - pub fn trees_ref(&self) -> CursorRef<'_> { - CursorRef::new(self) - } - pub fn trees(&self) -> Cursor { self.clone().into_trees() } @@ -341,7 +471,7 @@ pub fn eq_unspanned(&self, other: &TokenStream) -> bool { let mut t1 = self.trees(); let mut t2 = other.trees(); - for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { + for (t1, t2) in iter::zip(&mut t1, &mut t2) { if !t1.eq_unspanned(&t2) { return false; } @@ -427,10 +557,6 @@ } impl<'t> CursorRef<'t> { - fn new(stream: &TokenStream) -> CursorRef<'_> { - CursorRef { stream, index: 0 } - } - fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> { self.stream.0.get(self.index).map(|tree| { self.index += 1; @@ -477,6 +603,10 @@ } } + pub fn index(&self) -> usize { + self.index + } + pub fn append(&mut self, new_stream: TokenStream) { if new_stream.is_empty() { return; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/visit.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/visit.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast/src/visit.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast/src/visit.rs 2021-06-17 03:53:50.000000000 +0000 @@ -835,7 +835,6 @@ match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -848,6 +847,9 @@ visitor.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => { + visitor.visit_anon_const(anon_const) + } } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/expr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/expr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/expr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/expr.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1411,9 +1411,9 @@ out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)), } } - InlineAsmOperand::Const { ref expr } => { - hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) } - } + InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const { + anon_const: self.lower_anon_const(anon_const), + }, InlineAsmOperand::Sym { ref expr } => { hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) } } @@ -1499,46 +1499,64 @@ // previous iteration. required_features.clear(); - // Validate register classes against currently enabled target - // features. We check that at least one type is available for - // the current target. let reg_class = reg.reg_class(); if reg_class == asm::InlineAsmRegClass::Err { continue; } - for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { - if let Some(feature) = feature { - if self.sess.target_features.contains(&Symbol::intern(feature)) { + + // We ignore target feature requirements for clobbers: if the + // feature is disabled then the compiler doesn't care what we + // do with the registers. + // + // Note that this is only possible for explicit register + // operands, which cannot be used in the asm string. + let is_clobber = matches!( + op, + hir::InlineAsmOperand::Out { + reg: asm::InlineAsmRegOrRegClass::Reg(_), + late: _, + expr: None + } + ); + + if !is_clobber { + // Validate register classes against currently enabled target + // features. We check that at least one type is available for + // the current target. + for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { + if let Some(feature) = feature { + if self.sess.target_features.contains(&Symbol::intern(feature)) { + required_features.clear(); + break; + } else { + required_features.push(feature); + } + } else { required_features.clear(); break; - } else { - required_features.push(feature); } - } else { - required_features.clear(); - break; } - } - // We are sorting primitive strs here and can use unstable sort here - required_features.sort_unstable(); - required_features.dedup(); - match &required_features[..] { - [] => {} - [feature] => { - let msg = format!( - "register class `{}` requires the `{}` target feature", - reg_class.name(), - feature - ); - sess.struct_span_err(op_sp, &msg).emit(); - } - features => { - let msg = format!( - "register class `{}` requires at least one target feature: {}", - reg_class.name(), - features.join(", ") - ); - sess.struct_span_err(op_sp, &msg).emit(); + // We are sorting primitive strs here and can use unstable sort here + required_features.sort_unstable(); + required_features.dedup(); + match &required_features[..] { + [] => {} + [feature] => { + let msg = format!( + "register class `{}` requires the `{}` target feature", + reg_class.name(), + feature + ); + sess.struct_span_err(op_sp, &msg).emit(); + } + features => { + let msg = format!( + "register class `{}` requires at least one target feature: {}", + reg_class.name(), + features.join(", ") + ); + sess.struct_span_err(op_sp, &msg).emit(); + } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/item.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/item.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/item.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/item.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,6 +18,7 @@ use smallvec::{smallvec, SmallVec}; use tracing::debug; +use std::iter; use std::mem; pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { @@ -206,7 +207,7 @@ UseTreeKind::Glob => {} UseTreeKind::Simple(_, id1, id2) => { for (_, &id) in - self.expect_full_res_from_use(base_id).skip(1).zip([id1, id2].iter()) + iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { vec.push(id); } @@ -537,7 +538,7 @@ // won't be dealing with macros in the rest of the compiler. // Essentially a single `use` which imports two names is desugared into // two imports. - for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) { + for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { @@ -835,9 +836,17 @@ (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names))) } AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => { - let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); - let (generics, sig) = - self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id); + let asyncness = sig.header.asyncness; + let body_id = + self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body)); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + trait_item_def_id, + false, + asyncness.opt_return_id(), + i.id, + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id))) } AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_lowering/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_lowering/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -31,13 +31,14 @@ //! in the HIR, especially for multiple identifiers. #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_patterns)] +#![feature(iter_zip)] #![recursion_limit = "256"] use rustc_ast::node_id::NodeMap; -use rustc_ast::token::{self, DelimToken, Nonterminal, Token}; -use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, DelimSpan, TokenStream, TokenTree}; +use rustc_ast::token::{self, Token}; +use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::walk_list; use rustc_ast::{self as ast, *}; @@ -55,7 +56,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::parse::ParseSess; +use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind}; @@ -92,7 +93,7 @@ /// HACK(Centril): there is a cyclic dependency between the parser and lowering /// if we don't have this function pointer. To avoid that dependency so that - /// librustc_middle is independent of the parser, we use dynamic dispatch here. + /// `rustc_middle` is independent of the parser, we use dynamic dispatch here. nt_to_tokenstream: NtToTokenstream, /// Used to allocate HIR nodes. @@ -212,8 +213,6 @@ ) -> LocalDefId; } -type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream; - /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] @@ -402,42 +401,6 @@ PassThrough, } -struct TokenStreamLowering<'a> { - parse_sess: &'a ParseSess, - synthesize_tokens: CanSynthesizeMissingTokens, - nt_to_tokenstream: NtToTokenstream, -} - -impl<'a> TokenStreamLowering<'a> { - fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream { - tokens.into_trees().flat_map(|tree| self.lower_token_tree(tree).into_trees()).collect() - } - - fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { - match tree { - TokenTree::Token(token) => self.lower_token(token), - TokenTree::Delimited(span, delim, tts) => { - TokenTree::Delimited(span, delim, self.lower_token_stream(tts)).into() - } - } - } - - fn lower_token(&mut self, token: Token) -> TokenStream { - match token.kind { - token::Interpolated(nt) => { - let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens); - TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimToken::NoDelim, - self.lower_token_stream(tts), - ) - .into() - } - _ => TokenTree::Token(token).into(), - } - } -} - impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> { /// Full-crate AST visitor that inserts into a fresh @@ -520,10 +483,6 @@ } self.visit_fn_ret_ty(&f.decl.output) } - TyKind::ImplTrait(def_node_id, _) => { - self.lctx.allocate_hir_id_counter(def_node_id); - visit::walk_ty(self, t); - } _ => visit::walk_ty(self, t), } } @@ -572,7 +531,7 @@ } hir::Crate { - item: hir::CrateItem { module, span: c.span }, + item: module, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), items: self.items, @@ -1040,12 +999,12 @@ } } - let tokens = TokenStreamLowering { + let tokens = FlattenNonterminals { parse_sess: &self.sess.parse_sess, synthesize_tokens: CanSynthesizeMissingTokens::Yes, nt_to_tokenstream: self.nt_to_tokenstream, } - .lower_token(token.clone()); + .process_token(token.clone()); MacArgs::Eq(eq_span, unwrap_single_token(self.sess, tokens, token.span)) } } @@ -1056,12 +1015,12 @@ tokens: TokenStream, synthesize_tokens: CanSynthesizeMissingTokens, ) -> TokenStream { - TokenStreamLowering { + FlattenNonterminals { parse_sess: &self.sess.parse_sess, synthesize_tokens, nt_to_tokenstream: self.nt_to_tokenstream, } - .lower_token_stream(tokens) + .process_token_stream(tokens) } /// Given an associated type constraint like one of these: @@ -1431,14 +1390,10 @@ // Add a definition for the in-band `Param`. let def_id = self.resolver.local_def_id(def_node_id); - self.allocate_hir_id_counter(def_node_id); - - let hir_bounds = self.with_hir_id_owner(def_node_id, |this| { - this.lower_param_bounds( - bounds, - ImplTraitContext::Universal(in_band_ty_params, parent_def_id), - ) - }); + let hir_bounds = self.lower_param_bounds( + bounds, + ImplTraitContext::Universal(in_band_ty_params, parent_def_id), + ); // Set the name to `impl Bound1 + Bound2`. let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); in_band_ty_params.push(hir::GenericParam { @@ -2266,13 +2221,7 @@ let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty( - x, - ImplTraitContext::OtherOpaqueTy { - capturable_lifetimes: &mut FxHashSet::default(), - origin: hir::OpaqueTyOrigin::Misc, - }, - ) + self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other)) }), synthetic: param .attrs @@ -2290,7 +2239,6 @@ this.lower_ty(&ty, ImplTraitContext::disallowed()) }); let default = default.as_ref().map(|def| self.lower_anon_const(def)); - (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default }) } }; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_passes/src/ast_validation.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_passes/src/ast_validation.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_passes/src/ast_validation.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_passes/src/ast_validation.rs 2021-06-17 03:53:50.000000000 +0000 @@ -532,6 +532,25 @@ } } + /// 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() { + let n = 83942; + self.err_handler() + .struct_span_err( + ident.span, + "items in `extern` blocks cannot use non-ascii identifiers", + ) + .span_label(self.current_extern_span(), "in this `extern` block") + .note(&format!( + "This limitation may be lifted in the future; see issue #{} for more information", + n, n, + )) + .emit(); + } + } + /// Reject C-varadic type unless the function is foreign, /// or free and `unsafe extern "C"` semantically. fn check_c_varadic_type(&self, fk: FnKind<'a>) { @@ -592,7 +611,7 @@ self.session, ident.span, E0754, - "trying to load file for module `{}` with non ascii identifer name", + "trying to load file for module `{}` with non-ascii identifier name", ident.name ) .help("consider using `#[path]` attribute to specify filesystem path") @@ -735,7 +754,7 @@ GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().const_generics; + let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) } }; @@ -1103,15 +1122,18 @@ self.check_defaultness(fi.span, *def); self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => { self.check_defaultness(fi.span, *def); self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::MacCall(..) => {} } @@ -1150,20 +1172,23 @@ } fn visit_generics(&mut self, generics: &'a Generics) { - let mut prev_ty_default = None; + let cg_defaults = self.session.features_untracked().const_generics_defaults; + + let mut prev_param_default = None; for param in &generics.params { match param.kind { GenericParamKind::Lifetime => (), - GenericParamKind::Type { default: Some(_), .. } => { - prev_ty_default = Some(param.ident.span); + GenericParamKind::Type { default: Some(_), .. } + | GenericParamKind::Const { default: Some(_), .. } => { + prev_param_default = Some(param.ident.span); } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - if let Some(span) = prev_ty_default { + if let Some(span) = prev_param_default { let mut err = self.err_handler().struct_span_err( span, - "type parameters with a default must be trailing", + "generic parameters with a default must be trailing", ); - if matches!(param.kind, GenericParamKind::Const { .. }) { + 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", @@ -1188,8 +1213,41 @@ deny_equality_constraints(self, predicate, generics); } } - - visit::walk_generics(self, generics) + walk_list!(self, visit_generic_param, &generics.params); + for predicate in &generics.where_clause.predicates { + match predicate { + WherePredicate::BoundPredicate(bound_pred) => { + // A type binding, eg `for<'c> Foo: Send+Clone+'c` + self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); + + // This is slightly complicated. Our representation for poly-trait-refs contains a single + // binder and thus we only allow a single level of quantification. However, + // the syntax of Rust permits quantification in two places in where clauses, + // e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are + // defined, then error. + if !bound_pred.bound_generic_params.is_empty() { + for bound in &bound_pred.bounds { + match bound { + GenericBound::Trait(t, _) => { + if !t.bound_generic_params.is_empty() { + struct_span_err!( + self.err_handler(), + t.span, + E0316, + "nested quantification of lifetimes" + ) + .emit(); + } + } + GenericBound::Outlives(_) => {} + } + } + } + } + _ => {} + } + self.visit_where_predicate(predicate); + } } fn visit_generic_param(&mut self, param: &'a GenericParam) { @@ -1238,14 +1296,6 @@ visit::walk_pat(self, pat) } - fn visit_where_predicate(&mut self, p: &'a WherePredicate) { - if let &WherePredicate::BoundPredicate(ref bound_predicate) = p { - // A type binding, eg `for<'c> Foo: Send+Clone+'c` - self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params); - } - visit::walk_where_predicate(self, p); - } - 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); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_passes/src/feature_gate.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_passes/src/feature_gate.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_passes/src/feature_gate.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_passes/src/feature_gate.rs 2021-06-17 03:53:50.000000000 +0000 @@ -8,7 +8,7 @@ use rustc_session::parse::{feature_err, feature_err_issue}; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use rustc_span::Span; use tracing::debug; @@ -196,6 +196,14 @@ "thiscall-unwind ABI is experimental and subject to change" ); } + "wasm" => { + gate_feature_post!( + &self, + wasm_abi, + span, + "wasm ABI is experimental and subject to change" + ); + } abi => self .sess .parse_sess @@ -313,24 +321,13 @@ include => external_doc cfg => doc_cfg masked => doc_masked - spotlight => doc_spotlight + notable_trait => doc_notable_trait keyword => doc_keyword ); } } } - fn visit_name(&mut self, sp: Span, name: Symbol) { - if !name.as_str().is_ascii() { - gate_feature_post!( - &self, - non_ascii_idents, - self.sess.parse_sess.source_map().guess_head_span(sp), - "non-ascii idents are not fully supported" - ); - } - } - fn visit_item(&mut self, i: &'a ast::Item) { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { @@ -358,16 +355,6 @@ over time" ); } - if self.sess.contains_name(&i.attrs[..], sym::main) { - gate_feature_post!( - &self, - main, - i.span, - "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required" - ); - } } ast::ItemKind::Struct(..) => { @@ -599,12 +586,7 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { let is_fn = match i.kind { - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => { - if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { - gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); - } - true - } + ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( @@ -686,7 +668,6 @@ "to use an async block, remove the `||`: `async {`" ); gate_all!(generators, "yield syntax is experimental"); - gate_all!(or_patterns, "or-patterns syntax is experimental"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); @@ -705,7 +686,6 @@ // involved, so we only emit errors where there are no other parsing errors. gate_all!(destructuring_assignment, "destructuring assignments are unstable"); } - gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). @@ -741,16 +721,46 @@ } fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { + use rustc_errors::Applicability; + if !sess.opts.unstable_features.is_nightly_build() { + let lang_features = &sess.features_untracked().declared_lang_features; for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) { - struct_span_err!( + let mut err = struct_span_err!( sess.parse_sess.span_diagnostic, attr.span, E0554, "`#![feature]` may not be used on the {} release channel", option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)") - ) - .emit(); + ); + let mut all_stable = true; + for ident in + attr.meta_item_list().into_iter().flatten().map(|nested| nested.ident()).flatten() + { + let name = ident.name; + let stable_since = lang_features + .iter() + .flat_map(|&(feature, _, since)| if feature == name { since } else { None }) + .next(); + if let Some(since) = stable_since { + err.help(&format!( + "the feature `{}` has been stable since {} and no longer requires \ + an attribute to enable", + name, since + )); + } else { + all_stable = false; + } + } + if all_stable { + err.span_suggestion( + attr.span, + "remove the attribute", + String::new(), + Applicability::MachineApplicable, + ); + } + err.emit(); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_patterns)] #![recursion_limit = "256"] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -22,10 +22,6 @@ State::new().token_to_string(token) } -pub fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String { - State::new().token_to_string_ext(token, convert_dollar_crate) -} - pub fn ty_to_string(ty: &ast::Ty) -> String { State::new().ty_to_string(ty) } @@ -50,18 +46,10 @@ State::new().tts_to_string(tokens) } -pub fn stmt_to_string(stmt: &ast::Stmt) -> String { - State::new().stmt_to_string(stmt) -} - pub fn item_to_string(i: &ast::Item) -> String { State::new().item_to_string(i) } -pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String { - State::new().generic_params_to_string(generic_params) -} - pub fn path_to_string(p: &ast::Path) -> String { State::new().path_to_string(p) } @@ -74,26 +62,14 @@ State::new().vis_to_string(v) } -pub fn block_to_string(blk: &ast::Block) -> String { - State::new().block_to_string(blk) -} - pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String { State::new().meta_list_item_to_string(li) } -pub fn attr_item_to_string(ai: &ast::AttrItem) -> String { - State::new().attr_item_to_string(ai) -} - pub fn attribute_to_string(attr: &ast::Attribute) -> String { State::new().attribute_to_string(attr) } -pub fn param_to_string(arg: &ast::Param) -> String { - State::new().param_to_string(arg) -} - pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { State::new().to_string(f) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/state.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/state.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/state.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ast_pretty/src/pprust/state.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2149,10 +2149,10 @@ None => s.word("_"), } } - InlineAsmOperand::Const { expr } => { + InlineAsmOperand::Const { anon_const } => { s.word("const"); s.space(); - s.print_expr(expr); + s.print_expr(&anon_const.value); } InlineAsmOperand::Sym { expr } => { s.word("sym"); @@ -2292,10 +2292,6 @@ } } - pub fn print_usize(&mut self, i: usize) { - self.s.word(i.to_string()) - } - crate fn print_name(&mut self, name: Symbol) { self.s.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) @@ -2659,8 +2655,10 @@ s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { + s.s.space(); + s.word_space("="); + s.print_expr(&default.value); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_attr/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_attr/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_attr/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_attr/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,7 +4,7 @@ //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax` //! to this crate. -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #[macro_use] extern crate rustc_macros; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/asm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/asm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/asm.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/asm.rs 2021-06-17 03:53:50.000000000 +0000 @@ -7,11 +7,10 @@ use rustc_expand::base::{self, *}; use rustc_parse::parser::Parser; use rustc_parse_format as parse; -use rustc_span::{ - symbol::{kw, sym, Symbol}, - BytePos, -}; +use rustc_session::lint; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span}; +use rustc_target::asm::InlineAsmArch; struct AsmArgs { templates: Vec>, @@ -137,8 +136,8 @@ ast::InlineAsmOperand::InOut { reg, expr, late: true } } } else if p.eat_keyword(kw::Const) { - let expr = p.parse_expr()?; - ast::InlineAsmOperand::Const { expr } + let anon_const = p.parse_anon_const_expr()?; + ast::InlineAsmOperand::Const { anon_const } } else if p.eat_keyword(sym::sym) { let expr = p.parse_expr()?; match expr.kind { @@ -402,8 +401,6 @@ let mut line_spans = Vec::with_capacity(args.templates.len()); let mut curarg = 0; - let default_dialect = ecx.sess.inline_asm_dialect(); - for template_expr in args.templates.into_iter() { if !template.is_empty() { template.push(ast::InlineAsmTemplatePiece::String("\n".to_string())); @@ -430,56 +427,36 @@ let template_str = &template_str.as_str(); let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok(); - if let Some(snippet) = &template_snippet { - let snippet = snippet.trim_matches('"'); - match default_dialect { - ast::LlvmAsmDialect::Intel => { - if let Some(span) = check_syntax_directive(snippet, ".intel_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues"); - err.span_suggestion( - span, - "remove this assembler directive", - "".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } - - if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "using the .att_syntax directive may cause issues, use the att_syntax option instead"); - let asm_end = sp.hi() - BytePos(2); - let suggestions = vec![ - (span, "".to_string()), - ( - Span::new(asm_end, asm_end, sp.ctxt()), - ", options(att_syntax)".to_string(), - ), - ]; - err.multipart_suggestion( - "remove the assembler directive and replace it with options(att_syntax)", - suggestions, - Applicability::MachineApplicable, - ); - err.emit(); + if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch { + let find_span = |needle: &str| -> Span { + if let Some(snippet) = &template_snippet { + if let Some(pos) = snippet.find(needle) { + let end = pos + + &snippet[pos..] + .find(|c| matches!(c, '\n' | ';' | '\\' | '"')) + .unwrap_or(snippet[pos..].len() - 1); + let inner = InnerSpan::new(pos, end); + return template_sp.from_inner(inner); } } - ast::LlvmAsmDialect::Att => { - if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues"); - err.span_suggestion( - span, - "remove this assembler directive", - "".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } + template_sp + }; - // Use of .intel_syntax is ignored - } + if template_str.contains(".intel_syntax") { + ecx.parse_sess().buffer_lint( + lint::builtin::BAD_ASM_STYLE, + find_span(".intel_syntax"), + ecx.resolver.lint_node_id(ecx.current_expansion.id), + "avoid using `.intel_syntax`, Intel syntax is the default", + ); + } + if template_str.contains(".att_syntax") { + ecx.parse_sess().buffer_lint( + lint::builtin::BAD_ASM_STYLE, + find_span(".att_syntax"), + ecx.resolver.lint_node_id(ecx.current_expansion.id), + "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead", + ); } } @@ -690,15 +667,3 @@ } } } - -fn check_syntax_directive>(piece: S, syntax: &str) -> Option { - let piece = piece.as_ref(); - if let Some(idx) = piece.find(syntax) { - let end = - idx + &piece[idx..].find(|c| matches!(c, '\n' | ';')).unwrap_or(piece[idx..].len()); - // Offset by one because these represent the span with the " removed - Some(InnerSpan::new(idx + 1, end + 1)) - } else { - None - } -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/cfg_eval.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,11 +1,18 @@ use crate::util::check_builtin_macro_attribute; -use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AstLike}; +use rustc_ast as ast; +use rustc_ast::mut_visit::MutVisitor; +use rustc_ast::tokenstream::CanSynthesizeMissingTokens; +use rustc_ast::visit::Visitor; +use rustc_ast::{mut_visit, visit}; +use rustc_ast::{AstLike, Attribute}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; +use rustc_parse::parser::ForceCollect; +use rustc_session::utils::FlattenNonterminals; + +use rustc_ast::ptr::P; use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; @@ -22,74 +29,179 @@ crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec { let mut visitor = CfgEval { - cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }, + cfg: &mut StripUnconfigured { + sess: ecx.sess, + features: ecx.ecfg.features, + config_tokens: true, + }, }; - let mut annotatable = visitor.configure_annotatable(annotatable); - if visitor.cfg.modified { - // Erase the tokens if cfg-stripping modified the item - // This will cause us to synthesize fake tokens - // when `nt_to_tokenstream` is called on this item. - if let Some(tokens) = annotatable.tokens_mut() { - *tokens = None; + let annotatable = visitor.configure_annotatable(annotatable); + vec![annotatable] +} + +struct CfgEval<'a, 'b> { + cfg: &'a mut StripUnconfigured<'b>, +} + +fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable { + // Since the item itself has already been configured by the InvocationCollector, + // we know that fold result vector will contain exactly one element + match annotatable { + Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()), + Annotatable::TraitItem(item) => { + Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap()) + } + Annotatable::ImplItem(item) => { + Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap()) } + Annotatable::ForeignItem(item) => { + Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap()) + } + Annotatable::Stmt(stmt) => { + Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap())) + } + Annotatable::Expr(mut expr) => Annotatable::Expr({ + vis.visit_expr(&mut expr); + expr + }), + Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()), + Annotatable::ExprField(field) => { + Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap()) + } + Annotatable::PatField(fp) => { + Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap()) + } + Annotatable::GenericParam(param) => { + Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap()) + } + Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()), + Annotatable::FieldDef(sf) => { + Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap()) + } + Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()), } - vec![annotatable] } -struct CfgEval<'a> { - cfg: StripUnconfigured<'a>, +struct CfgFinder { + has_cfg_or_cfg_attr: bool, } -impl CfgEval<'_> { +impl CfgFinder { + fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { + let mut finder = CfgFinder { has_cfg_or_cfg_attr: false }; + match annotatable { + Annotatable::Item(item) => finder.visit_item(&item), + Annotatable::TraitItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Trait), + Annotatable::ImplItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Impl), + Annotatable::ForeignItem(item) => finder.visit_foreign_item(&item), + Annotatable::Stmt(stmt) => finder.visit_stmt(&stmt), + Annotatable::Expr(expr) => finder.visit_expr(&expr), + Annotatable::Arm(arm) => finder.visit_arm(&arm), + Annotatable::ExprField(field) => finder.visit_expr_field(&field), + Annotatable::PatField(field) => finder.visit_pat_field(&field), + Annotatable::GenericParam(param) => finder.visit_generic_param(¶m), + Annotatable::Param(param) => finder.visit_param(¶m), + Annotatable::FieldDef(field) => finder.visit_field_def(&field), + Annotatable::Variant(variant) => finder.visit_variant(&variant), + }; + finder.has_cfg_or_cfg_attr + } +} + +impl<'ast> visit::Visitor<'ast> for CfgFinder { + fn visit_attribute(&mut self, attr: &'ast Attribute) { + // We want short-circuiting behavior, so don't use the '|=' operator. + self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr + || attr + .ident() + .map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr); + } +} + +impl CfgEval<'_, '_> { fn configure(&mut self, node: T) -> Option { self.cfg.configure(node) } - fn configure_annotatable(&mut self, annotatable: Annotatable) -> Annotatable { - // Since the item itself has already been configured by the InvocationCollector, - // we know that fold result vector will contain exactly one element - match annotatable { - Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()), - Annotatable::TraitItem(item) => { - Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap()) - } - Annotatable::ImplItem(item) => { - Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap()) - } - Annotatable::ForeignItem(item) => { - Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap()) - } - Annotatable::Stmt(stmt) => { - Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap())) - } - Annotatable::Expr(mut expr) => Annotatable::Expr({ - self.visit_expr(&mut expr); - expr - }), - Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()), - Annotatable::ExprField(field) => { - Annotatable::ExprField(self.flat_map_expr_field(field).pop().unwrap()) - } - Annotatable::PatField(fp) => { - Annotatable::PatField(self.flat_map_pat_field(fp).pop().unwrap()) - } - Annotatable::GenericParam(param) => { - Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap()) - } - Annotatable::Param(param) => { - Annotatable::Param(self.flat_map_param(param).pop().unwrap()) - } - Annotatable::FieldDef(sf) => { - Annotatable::FieldDef(self.flat_map_field_def(sf).pop().unwrap()) - } - Annotatable::Variant(v) => { - Annotatable::Variant(self.flat_map_variant(v).pop().unwrap()) - } + pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable { + // Tokenizing and re-parsing the `Annotatable` can have a significant + // performance impact, so try to avoid it if possible + if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) { + return annotatable; } + + // The majority of parsed attribute targets will never need to have early cfg-expansion + // run (e.g. they are not part of a `#[derive]` or `#[cfg_eval]` macro inoput). + // Therefore, we normally do not capture the necessary information about `#[cfg]` + // and `#[cfg_attr]` attributes during parsing. + // + // Therefore, when we actually *do* run early cfg-expansion, we need to tokenize + // and re-parse the attribute target, this time capturing information about + // 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 mut orig_tokens = rustc_parse::nt_to_tokenstream( + &nt, + &self.cfg.sess.parse_sess, + CanSynthesizeMissingTokens::No, + ); + + // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) + // to `None`-delimited groups containing the corresponding tokens. This + // is normally delayed until the proc-macro server actually needs to + // provide a `TokenKind::Interpolated` to a proc-macro. We do this earlier, + // so that we can handle cases like: + // + // ```rust + // #[cfg_eval] #[cfg] $item + //``` + // + // where `$item` is `#[cfg_attr] struct Foo {}`. We want to make + // sure to evaluate *all* `#[cfg]` and `#[cfg_attr]` attributes - the simplest + // way to do this is to do a single parse of a stream without any nonterminals. + let mut flatten = FlattenNonterminals { + nt_to_tokenstream: rustc_parse::nt_to_tokenstream, + parse_sess: &self.cfg.sess.parse_sess, + synthesize_tokens: CanSynthesizeMissingTokens::No, + }; + orig_tokens = flatten.process_token_stream(orig_tokens); + + // Re-parse the tokens, setting the `capture_cfg` flag to save extra information + // to the captured `AttrAnnotatedTokenStream` (specifically, we capture + // `AttrAnnotatedTokenTree::AttributesData` for all occurences of `#[cfg]` and `#[cfg_attr]`) + 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!(), + }; + + // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring + // our attribute target will correctly the tokens as well. + flat_map_annotatable(self, annotatable) } } -impl MutVisitor for CfgEval<'_> { +impl MutVisitor for CfgEval<'_, '_> { fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); mut_visit::noop_visit_expr(expr, self); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/derive.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/derive.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/derive.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/derive.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ use crate::cfg_eval::cfg_eval; -use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; @@ -26,32 +26,39 @@ return ExpandResult::Ready(vec![item]); } - let template = - AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; - let attr = ecx.attribute(meta_item.clone()); - validate_attr::check_builtin_attribute(&sess.parse_sess, &attr, sym::derive, template); - - let derives: Vec<_> = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(meta) => Some(meta), - NestedMetaItem::Literal(lit) => { - // Reject `#[derive("Debug")]`. - report_unexpected_literal(sess, &lit); - None - } - }) - .map(|meta| { - // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. - report_path_args(sess, &meta); - meta.path - }) - .collect(); + let result = + ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { + let template = + AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; + let attr = attr::mk_attr_outer(meta_item.clone()); + validate_attr::check_builtin_attribute( + &sess.parse_sess, + &attr, + sym::derive, + template, + ); + + attr.meta_item_list() + .unwrap_or_default() + .into_iter() + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(meta) => Some(meta), + NestedMetaItem::Literal(lit) => { + // Reject `#[derive("Debug")]`. + report_unexpected_literal(sess, &lit); + None + } + }) + .map(|meta| { + // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. + report_path_args(sess, &meta); + meta.path + }) + .map(|path| (path, None)) + .collect() + }); - // FIXME: Try to cache intermediate results to avoid collecting same paths multiple times. - match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) { + match result { Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)), Err(Indeterminate) => ExpandResult::Retry(item), } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,10 +15,12 @@ item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { + let span = cx.with_def_site_ctxt(span); let inline = cx.meta_word(span, sym::inline); let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span)); let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]); - let attrs = vec![cx.attribute(inline), cx.attribute(doc)]; + let no_coverage = cx.meta_word(span, sym::no_coverage); + let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)]; let trait_def = TraitDef { span, attributes: Vec::new(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -541,7 +541,7 @@ self.generics.to_generics(cx, self.span, type_ident, generics); // Create the generic parameters - params.extend(generics.params.iter().map(|param| match param.kind { + params.extend(generics.params.iter().map(|param| match ¶m.kind { GenericParamKind::Lifetime { .. } => param.clone(), GenericParamKind::Type { .. } => { // I don't think this can be moved out of the loop, since @@ -561,7 +561,18 @@ cx.typaram(self.span, param.ident, vec![], bounds, None) } - GenericParamKind::Const { .. } => param.clone(), + GenericParamKind::Const { ty, kw_span, .. } => { + let const_nodefault_kind = GenericParamKind::Const { + ty: ty.clone(), + kw_span: kw_span.clone(), + + // We can't have default values inside impl block + default: None, + }; + let mut param_clone = param.clone(); + param_clone.kind = const_nodefault_kind; + param_clone + } })); // and similarly for where clauses @@ -1034,7 +1045,7 @@ // make a series of nested matches, to destructure the // structs. This is actually right-to-left, but it shouldn't // matter. - for (arg_expr, pat) in self_args.iter().zip(patterns) { + for (arg_expr, pat) in iter::zip(self_args, patterns) { body = cx.expr_match( trait_.span, arg_expr.clone(), @@ -1351,7 +1362,7 @@ let mut discriminant_test = cx.expr_bool(sp, true); let mut first_ident = None; - for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { + for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { let self_addr = cx.expr_addr_of(sp, self_arg.clone()); let variant_value = deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); @@ -1571,9 +1582,7 @@ let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries); let pattern = match *struct_def { VariantData::Struct(..) => { - let field_pats = subpats - .into_iter() - .zip(&ident_exprs) + let field_pats = iter::zip(subpats, &ident_exprs) .map(|(pat, &(sp, ident, ..))| { if ident.is_none() { cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/global_allocator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/global_allocator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/global_allocator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/global_allocator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,31 +14,31 @@ ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, - mut item: Annotatable, + item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator); - let not_static = |item: Annotatable| { + let orig_item = item.clone(); + let not_static = || { ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); - vec![item] + vec![orig_item.clone()] }; - let orig_item = item.clone(); - let mut is_stmt = false; // Allow using `#[global_allocator]` on an item statement - if let Annotatable::Stmt(stmt) = &item { - if let StmtKind::Item(item_) = &stmt.kind { - item = Annotatable::Item(item_.clone()); - is_stmt = true; - } - } - - let item = match item { + // FIXME - if we get deref patterns, use them to reduce duplication here + let (item, is_stmt) = match &item { Annotatable::Item(item) => match item.kind { - ItemKind::Static(..) => item, - _ => return not_static(Annotatable::Item(item)), + ItemKind::Static(..) => (item, false), + _ => return not_static(), + }, + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item_) => match item_.kind { + ItemKind::Static(..) => (item_, true), + _ => return not_static(), + }, + _ => return not_static(), }, - _ => return not_static(item), + _ => return not_static(), }; // Generate a bunch of new items using the AllocFnFactory diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -7,8 +7,9 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![recursion_limit = "256"] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/test_harness.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/test_harness.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_builtin_macros/src/test_harness.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_builtin_macros/src/test_harness.rs 2021-06-17 03:53:50.000000000 +0000 @@ -142,7 +142,7 @@ ast::ItemKind::Fn(..) => { if sess.contains_name(&item.attrs, sym::start) { EntryPointType::Start - } else if sess.contains_name(&item.attrs, sym::main) { + } else if sess.contains_name(&item.attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { if depth == 1 { @@ -187,7 +187,7 @@ let attrs = attrs .into_iter() .filter(|attr| { - !self.sess.check_name(attr, sym::main) + !self.sess.check_name(attr, sym::rustc_main) && !self.sess.check_name(attr, sym::start) }) .chain(iter::once(allow_dead_code)) @@ -220,7 +220,7 @@ let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, - &[sym::main, sym::test, sym::rustc_attrs], + &[sym::test, sym::rustc_attrs], None, ); let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); @@ -247,7 +247,7 @@ /// By default this expands to /// /// ``` -/// #[main] +/// #[rustc_main] /// pub fn main() { /// extern crate test; /// test::test_main_static(&[ @@ -297,8 +297,8 @@ let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None))); - // #[main] - let main_meta = ecx.meta_word(sp, sym::main); + // #[rustc_main] + let main_meta = ecx.meta_word(sp, sym::rustc_main); let main_attr = ecx.attribute(main_meta); // pub fn main() { ... } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build.sh 2021-06-17 03:53:50.000000000 +0000 @@ -55,6 +55,7 @@ ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir" mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" +mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/" if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" fi @@ -64,12 +65,18 @@ ;; "llvm") cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/" + if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then + cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/" + fi ;; "clif") echo "[BUILD] sysroot" dir=$(pwd) cd "$target_dir" time "$dir/build_sysroot/build_sysroot.sh" + if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then + time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh" + fi cp lib/rustlib/*/lib/libstd-* lib/ ;; *) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh 2021-06-17 03:53:50.000000000 +0000 @@ -28,7 +28,7 @@ if [[ "$1" != "--debug" ]]; then sysroot_channel='release' # FIXME Enable incremental again once rust-lang/rust#74946 is fixed - CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=2" cargo build --target "$TARGET_TRIPLE" --release + CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release else sysroot_channel='debug' cargo build --target "$TARGET_TRIPLE" diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock 2021-06-17 03:53:50.000000000 +0000 @@ -16,9 +16,9 @@ [[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -110,9 +110,9 @@ [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -132,18 +132,18 @@ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" dependencies = [ "rustc-std-workspace-core", ] [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.lock rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.lock --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.lock 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.lock 2021-06-17 03:53:50.000000000 +0000 @@ -39,16 +39,16 @@ [[package]] name = "cranelift-bforest" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "byteorder", "cranelift-bforest", @@ -65,8 +65,8 @@ [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -74,18 +74,18 @@ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" [[package]] name = "cranelift-entity" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" [[package]] name = "cranelift-frontend" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen", "log", @@ -95,8 +95,8 @@ [[package]] name = "cranelift-jit" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", @@ -113,8 +113,8 @@ [[package]] name = "cranelift-module" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", @@ -125,8 +125,8 @@ [[package]] name = "cranelift-native" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen", "target-lexicon", @@ -134,8 +134,8 @@ [[package]] name = "cranelift-object" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -16,7 +16,7 @@ cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" } target-lexicon = "0.11.0" gimli = { version = "0.23.0", default-features = false, features = ["write"]} -object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "write", "coff", "elf", "macho", "pe"] } +object = { version = "0.23.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" @@ -75,3 +75,6 @@ [profile.release.package.syn] opt-level = 0 debug = false + +[package.metadata.rust-analyzer] +rustc_private = true diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/env_vars.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/env_vars.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/env_vars.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/env_vars.md 2021-06-17 03:53:50.000000000 +0000 @@ -8,5 +8,8 @@ to make it possible to use incremental mode for all analyses performed by rustc without caching object files when their content should have been changed by a change to cg_clif.
CG_CLIF_DISPLAY_CG_TIME
-
If "1", display the time it took to perform codegen for a crate
+
If "1", display the time it took to perform codegen for a crate.
+
CG_CLIF_ENABLE_VERIFIER
+
Enable the Cranelift ir verifier for all compilation passes. If not set it will only run once + before passing the clif ir to Cranelift for compilation. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/usage.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/usage.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/usage.md 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/docs/usage.md 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,66 @@ +# Usage + +rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. + +Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). + +## Cargo + +In the directory with your project (where you can do the usual `cargo build`), run: + +```bash +$ $cg_clif_dir/build/cargo.sh build +``` + +This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. + +## Rustc + +> You should prefer using the Cargo method. + +```bash +$ $cg_clif_dir/build/bin/cg_clif my_crate.rs +``` + +## Jit mode + +In jit mode cg_clif will immediately execute your code without creating an executable file. + +> This requires all dependencies to be available as dynamic library. +> The jit mode will probably need cargo integration to make this possible. + +```bash +$ $cg_clif_dir/build/cargo.sh jit +``` + +or + +```bash +$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs +``` + +There is also an experimental lazy jit mode. In this mode functions are only compiled once they are +first called. It currently does not work with multi-threaded programs. When a not yet compiled +function is called from another thread than the main thread, you will get an ICE. + +```bash +$ $cg_clif_dir/build/cargo.sh lazy-jit +``` + +## Shell + +These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. + +```bash +function jit_naked() { + echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic +} + +function jit() { + jit_naked "fn main() { $@ }" +} + +function jit_calc() { + jit 'println!("0x{:x}", ' $@ ');'; +} +``` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,4 @@ -#![feature( - no_core, start, lang_items, box_syntax, never_type, linkage, - extern_types, thread_local -)] +#![feature(no_core, lang_items, box_syntax, never_type, linkage, extern_types, thread_local)] #![no_core] #![allow(dead_code, non_camel_case_types)] @@ -239,7 +236,7 @@ assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] { extern { #[linkage = "extern_weak"] @@ -292,7 +289,7 @@ from_decimal_string(); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] test_tls(); #[cfg(all(not(jit), target_os = "linux"))] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/example/mini_core.rs 2021-06-17 03:53:50.000000000 +0000 @@ -621,6 +621,7 @@ } #[no_mangle] +#[cfg(not(windows))] pub fn get_tls() -> u8 { #[thread_local] static A: u8 = 42; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -name: Bootstrap rustc using cg_clif - -on: - - push - -jobs: - bootstrap_rustc: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Cache cargo installed crates - uses: actions/cache@v2 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-cargo-installed-crates - - - name: Cache cargo registry and index - uses: actions/cache@v2 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v2 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} - - - name: Prepare dependencies - run: | - git config --global user.email "user@example.com" - git config --global user.name "User" - ./prepare.sh - - - name: Test - run: | - # Enable backtraces for easier debugging - export RUST_BACKTRACE=1 - - ./scripts/test_bootstrap.sh diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/main.yml 2021-06-17 03:53:50.000000000 +0000 @@ -7,11 +7,18 @@ jobs: build: runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + - os: macos-latest + # cross-compile from Linux to Windows using mingw + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - uses: actions/checkout@v2 @@ -36,6 +43,12 @@ path: target key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + - name: Install MinGW toolchain and wine + if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: | + sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable + rustup target add x86_64-pc-windows-gnu + - name: Prepare dependencies run: | git config --global user.email "user@example.com" @@ -43,6 +56,8 @@ ./prepare.sh - name: Test + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: | # Enable backtraces for easier debugging export RUST_BACKTRACE=1 @@ -51,12 +66,16 @@ export COMPILE_RUNS=2 export RUN_RUNS=2 + # Enable extra checks + export CG_CLIF_ENABLE_VERIFIER=1 + ./test.sh - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build - name: Upload prebuilt cg_clif + if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' uses: actions/upload-artifact@v2 with: name: cg_clif-${{ runner.os }} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,82 @@ +name: Various rustc tests + +on: + - push + +jobs: + bootstrap_rustc: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Cache cargo installed crates + uses: actions/cache@v2 + with: + path: ~/.cargo/bin + key: ${{ runner.os }}-cargo-installed-crates + + - name: Cache cargo registry and index + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo target dir + uses: actions/cache@v2 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./prepare.sh + + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + ./scripts/test_bootstrap.sh + rustc_test_suite: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Cache cargo installed crates + uses: actions/cache@v2 + with: + path: ~/.cargo/bin + key: ${{ runner.os }}-cargo-installed-crates + + - name: Cache cargo registry and index + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo target dir + uses: actions/cache@v2 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./prepare.sh + + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + ./scripts/test_rustc_tests.sh diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/prepare.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/prepare.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/prepare.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/prepare.sh 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env bash set -e -rustup component add rust-src rustc-dev llvm-tools-preview ./build_sysroot/prepare_sysroot_src.sh cargo install hyperfine || echo "Skipping hyperfine install" diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Readme.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Readme.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/Readme.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/Readme.md 2021-06-17 03:53:50.000000000 +0000 @@ -34,70 +34,19 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). -### Cargo - In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh run -``` - -This should build and run your project with rustc_codegen_cranelift instead of the usual LLVM backend. - -### Rustc - -> You should prefer using the Cargo method. - -```bash -$ $cg_clif_dir/build/bin/cg_clif my_crate.rs -``` - -### Jit mode - -In jit mode cg_clif will immediately execute your code without creating an executable file. - -> This requires all dependencies to be available as dynamic library. -> The jit mode will probably need cargo integration to make this possible. - -```bash -$ $cg_clif_dir/build/cargo.sh jit -``` - -or - -```bash -$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs -``` - -There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. It currently does not work with multi-threaded programs. When a not yet compiled -function is called from another thread than the main thread, you will get an ICE. - -```bash -$ $cg_clif_dir/build/cargo.sh lazy-jit +$ $cg_clif_dir/build/cargo.sh build ``` -### Shell +This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. -These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. - -```bash -function jit_naked() { - echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic -} - -function jit() { - jit_naked "fn main() { $@ }" -} - -function jit_calc() { - jit 'println!("0x{:x}", ' $@ ');'; -} -``` +For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md). ## Env vars -[see env_vars.md](docs/env_vars.md) +See [env_vars.md](docs/env_vars.md) for all env vars used by rustc_codegen_cranelift. ## Not yet supported @@ -106,3 +55,20 @@ `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You have to specify specific registers instead. * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work) + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you shall be dual licensed as above, without any +additional terms or conditions. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/rust-toolchain rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/rust-toolchain --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/rust-toolchain 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/rust-toolchain 2021-06-17 03:53:50.000000000 +0000 @@ -1 +1,3 @@ -nightly-2021-03-05 +[toolchain] +channel = "nightly-2021-03-29" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/cargo.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/cargo.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/cargo.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/cargo.sh 2021-06-17 03:53:50.000000000 +0000 @@ -4,7 +4,7 @@ source "$dir/config.sh" # read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat "$dir/rust-toolchain") +TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/") cmd=$1 shift || true diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/config.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/config.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/config.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/config.sh 2021-06-17 03:53:50.000000000 +0000 @@ -2,15 +2,7 @@ set -e -unamestr=$(uname) -if [[ "$unamestr" == 'Linux' || "$unamestr" == 'FreeBSD' ]]; then - dylib_ext='so' -elif [[ "$unamestr" == 'Darwin' ]]; then - dylib_ext='dylib' -else - echo "Unsupported os" - exit 1 -fi +dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -) if echo "$RUSTC_WRAPPER" | grep sccache; then echo @@ -24,10 +16,10 @@ export RUSTC=$dir"/bin/cg_clif" export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\ -'-Zcodegen-backend='$dir'/lib/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir +'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir # FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$unamestr" == 'Darwin' ]]; then +if [[ "$(uname)" == 'Darwin' ]]; then export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" fi diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/rustup.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/rustup.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/rustup.sh 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/rustup.sh 2021-06-17 03:53:50.000000000 +0000 @@ -8,7 +8,7 @@ echo "=> Installing new nightly" rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists - echo "nightly-${TOOLCHAIN}" > rust-toolchain + sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain rustup component add rustfmt || true echo "=> Uninstalling all old nighlies" diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,68 @@ +#!/bin/bash +set -e + +./build.sh +source build/config.sh + +echo "[SETUP] Rust fork" +git clone https://github.com/rust-lang/rust.git || true +pushd rust +git fetch +git checkout -- . +git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" + +git apply - < config.toml < config.toml < res.txt - diff -u res.txt examples/regexdna-output.txt + ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + cat examples/regexdna-input.txt \ + | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | grep -v "Spawned thread" > res.txt + diff -u res.txt examples/regexdna-output.txt + fi - echo "[TEST] rust-lang/regex tests" - ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + echo "[TEST] rust-lang/regex tests" + ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + else + echo "[AOT] rust-lang/regex tests" + ../build/cargo.sh build --tests --target $TARGET_TRIPLE + fi popd } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/comments.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/comments.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/comments.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/comments.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,9 +11,11 @@ use crate::prelude::*; pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { - fx.add_global_comment( - "kind loc.idx param pass mode ty".to_string(), - ); + if fx.clif_comments.enabled() { + fx.add_global_comment( + "kind loc.idx param pass mode ty".to_string(), + ); + } } pub(super) fn add_arg_comment<'tcx>( @@ -25,6 +27,10 @@ arg_abi_mode: PassMode, arg_layout: TyAndLayout<'tcx>, ) { + if !fx.clif_comments.enabled() { + return; + } + let local = if let Some(local) = local { Cow::Owned(format!("{:?}", local)) } else { @@ -59,10 +65,12 @@ } pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { - fx.add_global_comment(String::new()); - fx.add_global_comment( - "kind local ty size align (abi,pref)".to_string(), - ); + if fx.clif_comments.enabled() { + fx.add_global_comment(String::new()); + fx.add_global_comment( + "kind local ty size align (abi,pref)".to_string(), + ); + } } pub(super) fn add_local_place_comments<'tcx>( @@ -70,6 +78,9 @@ place: CPlace<'tcx>, local: Local, ) { + if !fx.clif_comments.enabled() { + return; + } let TyAndLayout { ty, layout } = place.layout(); let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } = layout; @@ -90,7 +101,7 @@ } else { Cow::Borrowed("") }; - match ptr.base_and_offset() { + match ptr.debug_base_and_offset() { (crate::pointer::PointerBase::Addr(addr), offset) => { ("reuse", format!("storage={}{}{}", addr, offset, meta).into()) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,5 @@ //! Handling of everything related to the calling convention. Also fills `fx.local_map`. -#[cfg(debug_assertions)] mod comments; mod pass_mode; mod returning; @@ -75,8 +74,9 @@ let func_id = import_function(self.tcx, self.cx.module, inst); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); - #[cfg(debug_assertions)] - self.add_comment(func_ref, format!("{:?}", inst)); + if self.clif_comments.enabled() { + self.add_comment(func_ref, format!("{:?}", inst)); + } func_ref } @@ -92,8 +92,7 @@ let func_id = self.cx.module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); let call_inst = self.bcx.ins().call(func_ref, args); - #[cfg(debug_assertions)] - { + if self.clif_comments.enabled() { self.add_comment(call_inst, format!("easy_call {}", name)); } let results = self.bcx.inst_results(call_inst); @@ -149,7 +148,6 @@ CPlace::new_stack_slot(fx, layout) }; - #[cfg(debug_assertions)] self::comments::add_local_place_comments(fx, place, local); place @@ -163,7 +161,6 @@ let ssa_analyzed = crate::analyze::analyze(fx); - #[cfg(debug_assertions)] self::comments::add_args_header_comment(fx); let mut block_params_iter = fx.bcx.func.dfg.block_params(start_block).to_vec().into_iter(); @@ -228,7 +225,6 @@ fx.fn_abi = Some(fn_abi); assert!(block_params_iter.next().is_none(), "arg_value left behind"); - #[cfg(debug_assertions)] self::comments::add_locals_header_comment(fx); for (local, arg_kind, ty) in func_params { @@ -256,7 +252,6 @@ CPlace::for_ptr(addr, val.layout()) }; - #[cfg(debug_assertions)] self::comments::add_local_place_comments(fx, place, local); assert_eq!(fx.local_map.push(place), local); @@ -392,8 +387,7 @@ let (func_ref, first_arg) = match instance { // Trait object call Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); fx.add_comment( nop_inst, @@ -414,8 +408,7 @@ // Indirect call None => { - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); fx.add_comment(nop_inst, "indirect call"); } @@ -477,10 +470,7 @@ // FIXME find a cleaner way to support varargs if fn_sig.c_variadic { if !matches!(fn_sig.abi, Abi::C { .. }) { - fx.tcx.sess.span_fatal( - span, - &format!("Variadic call for non-C abi {:?}", fn_sig.abi), - ); + fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi)); } let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); let abi_params = call_args diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs 2021-06-17 03:53:50.000000000 +0000 @@ -208,7 +208,7 @@ }); let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); let mut offset = 0; - let mut block_params_iter = block_params.into_iter().copied(); + let mut block_params_iter = block_params.iter().copied(); for param in abi_params { let val = ptr.offset_i64(fx, offset).store( fx, @@ -248,8 +248,8 @@ /// as necessary. pub(super) fn cvalue_for_param<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option, + local: Option, + local_field: Option, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, block_params_iter: &mut impl Iterator, ) -> Option> { @@ -263,7 +263,6 @@ }) .collect::>(); - #[cfg(debug_assertions)] crate::abi::comments::add_arg_comment( fx, "arg", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/returning.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/returning.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/returning.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/abi/returning.rs 2021-06-17 03:53:50.000000000 +0000 @@ -84,10 +84,6 @@ } }; - #[cfg(not(debug_assertions))] - let _ = ret_param; - - #[cfg(debug_assertions)] crate::abi::comments::add_arg_comment( fx, "ret", @@ -146,7 +142,7 @@ let results = fx .bcx .inst_results(call_inst) - .into_iter() + .iter() .copied() .collect::>(); let result = diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/allocator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/allocator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/allocator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/allocator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,6 +3,7 @@ use crate::prelude::*; +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_span::symbol::sym; @@ -92,7 +93,7 @@ bcx.finalize(); } module - .define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap(); unwind_context.add_function(func_id, &ctx, module.isa()); } @@ -132,7 +133,7 @@ bcx.finalize(); } module - .define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap(); unwind_context.add_function(func_id, &ctx, module.isa()); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/base.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,6 @@ //! Codegen of a single function +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiExt; @@ -7,11 +8,7 @@ use crate::prelude::*; -pub(crate) fn codegen_fn<'tcx>( - cx: &mut crate::CodegenCx<'_, 'tcx>, - instance: Instance<'tcx>, - linkage: Linkage, -) { +pub(crate) fn codegen_fn<'tcx>(cx: &mut crate::CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { let tcx = cx.tcx; let _inst_guard = @@ -23,7 +20,7 @@ // Declare function let name = tcx.symbol_name(instance).name.to_string(); let sig = get_function_sig(tcx, cx.module.isa().triple(), instance); - let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap(); + let func_id = cx.module.declare_function(&name, Linkage::Local, &sig).unwrap(); cx.cached_context.clear(); @@ -131,7 +128,7 @@ let module = &mut cx.module; tcx.sess.time("define function", || { module - .define_function(func_id, context, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, context, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap() }); @@ -219,8 +216,7 @@ codegen_stmt(fx, block, stmt); } - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let mut terminator_head = "\n".to_string(); bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); let inst = fx.bcx.func.layout.last_inst(block).unwrap(); @@ -433,12 +429,14 @@ fx.set_debug_loc(stmt.source_info); - #[cfg(false_debug_assertions)] + #[cfg(disabled)] match &stmt.kind { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful _ => { - let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); - fx.add_comment(inst, format!("{:?}", stmt)); + if fx.clif_comments.enabled() { + let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); + fx.add_comment(inst, format!("{:?}", stmt)); + } } } @@ -464,16 +462,16 @@ let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout()); lval.write_cvalue(fx, val); } - Rvalue::BinaryOp(bin_op, box (ref lhs, ref rhs)) => { - let lhs = codegen_operand(fx, lhs); - let rhs = codegen_operand(fx, rhs); + Rvalue::BinaryOp(bin_op, ref lhs_rhs) => { + let lhs = codegen_operand(fx, &lhs_rhs.0); + let rhs = codegen_operand(fx, &lhs_rhs.1); let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs); lval.write_cvalue(fx, res); } - Rvalue::CheckedBinaryOp(bin_op, box (ref lhs, ref rhs)) => { - let lhs = codegen_operand(fx, lhs); - let rhs = codegen_operand(fx, rhs); + Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => { + let lhs = codegen_operand(fx, &lhs_rhs.0); + let rhs = codegen_operand(fx, &lhs_rhs.1); let res = if !fx.tcx.sess.overflow_checks() { let val = @@ -659,7 +657,9 @@ .val .try_to_bits(fx.tcx.data_layout.pointer_size) .unwrap(); - if fx.clif_type(operand.layout().ty) == Some(types::I8) { + if operand.layout().size.bytes() == 0 { + // Do nothing for ZST's + } else if fx.clif_type(operand.layout().ty) == Some(types::I8) { let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64); // FIXME use emit_small_memset where possible let addr = lval.to_ptr().get_addr(fx); @@ -832,25 +832,18 @@ } } StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"), - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - src, - dst, - count, - }) => { - let dst = codegen_operand(fx, dst); + StatementKind::CopyNonOverlapping(inner) => { + let dst = codegen_operand(fx, &inner.dst); let pointee = dst - .layout() - .pointee_info_at(fx, rustc_target::abi::Size::ZERO) - .expect("Expected pointer"); + .layout() + .pointee_info_at(fx, rustc_target::abi::Size::ZERO) + .expect("Expected pointer"); let dst = dst.load_scalar(fx); - let src = codegen_operand(fx, src).load_scalar(fx); - let count = codegen_operand(fx, count).load_scalar(fx); + let src = codegen_operand(fx, &inner.src).load_scalar(fx); + let count = codegen_operand(fx, &inner.count).load_scalar(fx); 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 - }; + let bytes = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/codegen_i128.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/codegen_i128.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/codegen_i128.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/codegen_i128.rs 2021-06-17 03:53:50.000000000 +0000 @@ -32,18 +32,56 @@ BinOp::Add | BinOp::Sub if !checked => None, BinOp::Mul if !checked => { let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + if fx.tcx.sess.target.is_like_windows { + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = + [ret_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + fx.lib_call( + "__multi3", + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + vec![], + &args, + ); + Some(ret_place.to_cvalue(fx)) + } else { + Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + } } BinOp::Add | BinOp::Sub | BinOp::Mul => { assert!(checked); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); - let param_types = vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), - AbiParam::new(types::I128), - AbiParam::new(types::I128), - ]; - let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let (param_types, args) = if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], + ) + } else { + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(types::I128), + AbiParam::new(types::I128), + ], + [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)], + ) + }; let name = match (bin_op, is_signed) { (BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, true) => "__rust_i128_addo", @@ -57,20 +95,33 @@ Some(out_place.to_cvalue(fx)) } BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), - BinOp::Div => { + BinOp::Div | BinOp::Rem => { assert!(!checked); - if is_signed { - Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128)) - } else { - Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128)) - } - } - BinOp::Rem => { - assert!(!checked); - if is_signed { - Some(fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128)) + let name = match (bin_op, is_signed) { + (BinOp::Div, false) => "__udivti3", + (BinOp::Div, true) => "__divti3", + (BinOp::Rem, false) => "__umodti3", + (BinOp::Rem, true) => "__modti3", + _ => unreachable!(), + }; + if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + let ret = fx.lib_call( + name, + vec![AbiParam::new(pointer_ty(fx.tcx)), AbiParam::new(pointer_ty(fx.tcx))], + vec![AbiParam::new(types::I64X2)], + &args, + )[0]; + // FIXME use bitcast instead of store to get from i64x2 to i128 + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); + Some(ret_place.to_cvalue(fx)) } else { - Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128)) + Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) } } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/common.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/common.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/common.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/common.rs 2021-06-17 03:53:50.000000000 +0000 @@ -361,8 +361,7 @@ let _ = self.cx.module.define_data(msg_id, &data_ctx); let local_msg_id = self.cx.module.declare_data_in_func(msg_id, self.bcx.func); - #[cfg(debug_assertions)] - { + if self.clif_comments.enabled() { self.add_comment(local_msg_id, msg); } self.bcx.ins().global_value(self.pointer_type, local_msg_id) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,41 @@ +macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) { + #[cfg(feature = "jit")] + #[allow(improper_ctypes)] + extern "C" { + $(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)* + } + + #[cfg(feature = "jit")] + pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) { + for &(name, val) in &[$((stringify!($name), $name as *const u8)),*] { + builder.symbol(name, val); + } + } +} + +builtin_functions! { + register_functions_for_jit; + + // integers + fn __multi3(a: i128, b: i128) -> i128; + fn __udivti3(n: u128, d: u128) -> u128; + fn __divti3(n: i128, d: i128) -> i128; + fn __umodti3(n: u128, d: u128) -> u128; + fn __modti3(n: i128, d: i128) -> i128; + fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool); + fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool); + fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool); + + // floats + fn __floattisf(i: i128) -> f32; + fn __floattidf(i: i128) -> f64; + fn __floatuntisf(i: u128) -> f32; + fn __floatuntidf(i: u128) -> f64; + fn __fixsfti(f: f32) -> i128; + fn __fixdfti(f: f64) -> i128; + fn __fixunssfti(f: f32) -> u128; + fn __fixunsdfti(f: f64) -> u128; +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/constant.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/constant.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/constant.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/constant.rs 2021-06-17 03:53:50.000000000 +0000 @@ -45,9 +45,9 @@ }; match const_.val { ConstKind::Value(_) => {} - ConstKind::Unevaluated(def, ref substs, promoted) => { + ConstKind::Unevaluated(unevaluated) => { if let Err(err) = - fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) + fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { all_constants_ok = false; match err { @@ -85,8 +85,9 @@ ) -> CValue<'tcx> { let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("tls {:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("tls {:?}", def_id)); + } let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id); CValue::by_val(tls_ptr, layout) } @@ -98,8 +99,9 @@ ) -> CPlace<'tcx> { let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", def_id)); + } let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); assert!(!layout.is_unsized(), "unsized statics aren't supported"); assert!( @@ -122,14 +124,16 @@ }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => { + ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if fx.tcx.is_static(def.did) => + { assert!(substs.is_empty()); assert!(promoted.is_none()); return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx); } - ConstKind::Unevaluated(def, ref substs, promoted) => { - match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) { + ConstKind::Unevaluated(unevaluated) => { + match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { Ok(const_val) => const_val, Err(_) => { span_bug!(constant.span, "erroneous constant not captured by required_consts"); @@ -183,8 +187,9 @@ data_id_for_alloc_id(fx.cx.module, ptr.alloc_id, alloc.mutability); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); + } fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } Some(GlobalAlloc::Function(instance)) => { @@ -199,8 +204,9 @@ let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", def_id)); + } fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } None => bug!("missing allocation {:?}", ptr.alloc_id), @@ -241,8 +247,9 @@ let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, alloc.mutability); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", alloc_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", alloc_id)); + } let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); crate::pointer::Pointer::new(global_ptr) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs 2021-06-17 03:53:50.000000000 +0000 @@ -39,11 +39,11 @@ #[cfg(unix)] { use std::os::unix::ffi::OsStrExt; - return path.as_bytes(); + path.as_bytes() } #[cfg(not(unix))] { - return path.to_str().unwrap().as_bytes(); + path.to_str().unwrap().as_bytes() } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/aot.rs 2021-06-17 03:53:50.000000000 +0000 @@ -119,11 +119,10 @@ tcx.sess.opts.debuginfo != DebugInfo::None, ); super::predefine_mono_items(&mut cx, &mono_items); - for (mono_item, (linkage, visibility)) in mono_items { - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage)); + cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst)); } MonoItem::Static(def_id) => { crate::constant::codegen_static(&mut cx.constants_cx, def_id) @@ -163,6 +162,21 @@ metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box<(CodegenResults, FxHashMap)> { + use rustc_span::symbol::sym; + + let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != sym::windows && subsystem != sym::console { + tcx.sess.fatal(&format!( + "invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem + )); + } + subsystem.to_string() + }); + let mut work_products = FxHashMap::default(); let cgus = if tcx.sess.opts.output_types.should_codegen() { @@ -280,7 +294,7 @@ allocator_module, metadata_module, metadata, - windows_subsystem: None, // Windows is not yet supported + windows_subsystem, linker_info: LinkerInfo::new(tcx), crate_info: CrateInfo::new(tcx), }, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/jit.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,8 +5,10 @@ use std::ffi::CString; use std::os::raw::{c_char, c_int}; +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; +use rustc_session::config::EntryFnType; use cranelift_jit::{JITBuilder, JITModule}; @@ -28,20 +30,11 @@ let mut jit_builder = JITBuilder::with_isa(crate::build_isa(tcx.sess), cranelift_module::default_libcall_names()); jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy)); + crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbols(imported_symbols); let mut jit_module = JITModule::new(jit_builder); assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type()); - let sig = Signature { - params: vec![ - AbiParam::new(jit_module.target_config().pointer_type()), - AbiParam::new(jit_module.target_config().pointer_type()), - ], - returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)], - call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), - }; - let main_func_id = jit_module.declare_function("main", Linkage::Import, &sig).unwrap(); - let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); let mono_items = cgus .iter() @@ -55,15 +48,12 @@ super::time(tcx, "codegen mono items", || { super::predefine_mono_items(&mut cx, &mono_items); - for (mono_item, (linkage, visibility)) in mono_items { - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => match backend_config.codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { - cx.tcx - .sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage)); + cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst)); } CodegenMode::JitLazy => codegen_shim(&mut cx, inst), }, @@ -86,24 +76,17 @@ tcx.sess.fatal("Inline asm is not supported in JIT mode"); } - crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context); crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context); tcx.sess.abort_if_errors(); jit_module.finalize_definitions(); - let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) }; - let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); - println!( "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed" ); - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = - unsafe { ::std::mem::transmute(finalized_main) }; - let args = ::std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new()); let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string()) .chain(args.split(' ')) @@ -118,12 +101,58 @@ BACKEND_CONFIG.with(|tls_backend_config| { assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none()) }); - CURRENT_MODULE - .with(|current_module| assert!(current_module.borrow_mut().replace(jit_module).is_none())); - let ret = f(args.len() as c_int, argv.as_ptr()); + let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap(); + let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); - std::process::exit(ret); + match entry_ty { + EntryFnType::Main => { + // FIXME set program arguments somehow + + let main_sig = Signature { + params: vec![], + returns: vec![], + call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + }; + let main_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig) + .unwrap(); + let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) }; + f(); + std::process::exit(0); + } + EntryFnType::Start => { + let start_sig = Signature { + params: vec![ + AbiParam::new(jit_module.target_config().pointer_type()), + AbiParam::new(jit_module.target_config().pointer_type()), + ], + returns: vec![AbiParam::new( + jit_module.target_config().pointer_type(), /*isize*/ + )], + call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + }; + let start_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig) + .unwrap(); + let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + let f: extern "C" fn(c_int, *const *const c_char) -> c_int = + unsafe { ::std::mem::transmute(finalized_start) }; + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); + } + } } #[no_mangle] @@ -144,8 +173,7 @@ jit_module.prepare_for_function_redefine(func_id).unwrap(); let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false); - tcx.sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, instance, Linkage::Export)); + tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance)); let (global_asm, _debug_context, unwind_context) = cx.finalize(); assert!(global_asm.is_empty()); @@ -220,7 +248,7 @@ imported_symbols } -pub(super) fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) { +fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) { let tcx = cx.tcx; let pointer_type = cx.module.target_config().pointer_type(); @@ -267,7 +295,8 @@ .define_function( func_id, &mut Context::for_function(trampoline), - &mut cranelift_codegen::binemit::NullTrapSink {}, + &mut NullTrapSink {}, + &mut NullStackMapSink {}, ) .unwrap(); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/driver/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -44,13 +44,19 @@ mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))], ) { cx.tcx.sess.time("predefine functions", || { + let is_compiler_builtins = cx.tcx.is_compiler_builtins(LOCAL_CRATE); for &(mono_item, (linkage, visibility)) in mono_items { match mono_item { MonoItem::Fn(instance) => { let name = cx.tcx.symbol_name(instance).name.to_string(); let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name)); let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance); - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + let linkage = crate::linkage::get_clif_linkage( + mono_item, + linkage, + visibility, + is_compiler_builtins, + ); cx.module.declare_function(&name, linkage, &sig).unwrap(); } MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/inline_asm.rs 2021-06-17 03:53:50.000000000 +0000 @@ -20,6 +20,10 @@ if template.is_empty() { // Black box return; + } else 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; } let mut slot_size = Size::from_bytes(0); @@ -193,8 +197,9 @@ offset: None, size: u32::try_from(slot_size.bytes()).unwrap(), }); - #[cfg(debug_assertions)] - fx.add_comment(stack_slot, "inline asm scratch slot"); + if fx.clif_comments.enabled() { + fx.add_comment(stack_slot, "inline asm scratch slot"); + } let inline_asm_func = fx .cx @@ -210,8 +215,9 @@ ) .unwrap(); let inline_asm_func = fx.cx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(inline_asm_func, asm_name); + if fx.clif_comments.enabled() { + fx.add_comment(inline_asm_func, asm_name); + } for (_reg, offset, value) in inputs { fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs 2021-06-17 03:53:50.000000000 +0000 @@ -88,7 +88,7 @@ let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { let ptr = Pointer::new(AllocId(0 /* dummy */), offset); - let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */); + let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */); alloc.get_bytes(fx, ptr, size).unwrap() } _ => unreachable!("{:?}", idx_const), @@ -277,5 +277,7 @@ // simd_select // simd_rem // simd_neg + // simd_trunc + // simd_floor } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,13 +1,4 @@ -#![feature( - rustc_private, - decl_macro, - type_alias_impl_trait, - associated_type_bounds, - never_type, - try_blocks, - box_patterns, - hash_drain_filter -)] +#![feature(rustc_private, decl_macro, never_type, hash_drain_filter)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] @@ -57,6 +48,7 @@ mod cast; mod codegen_i128; mod common; +mod compiler_builtins; mod constant; mod debuginfo; mod discriminant; @@ -224,8 +216,10 @@ impl CodegenBackend for CraneliftCodegenBackend { fn init(&self, sess: &Session) { - if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode { - sess.warn("LTO is not supported. You may get a linker error."); + use rustc_session::config::Lto; + match sess.lto() { + Lto::No | Lto::ThinLocal => {} + Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."), } } @@ -240,9 +234,9 @@ vec![] } - fn codegen_crate<'tcx>( + fn codegen_crate( &self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { @@ -252,9 +246,7 @@ BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.fatal(&err)) }; - let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config); - - res + driver::codegen_crate(tcx, metadata, need_metadata_module, config) } fn join_codegen( @@ -300,9 +292,9 @@ let mut flags_builder = settings::builder(); flags_builder.enable("is_pic").unwrap(); flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided - flags_builder - .set("enable_verifier", if cfg!(debug_assertions) { "true" } else { "false" }) - .unwrap(); + let enable_verifier = + cfg!(debug_assertions) || std::env::var("CG_CLIF_ENABLE_VERIFIER").is_ok(); + flags_builder.set("enable_verifier", if enable_verifier { "true" } else { "false" }).unwrap(); let tls_model = match target_triple.binary_format { BinaryFormat::Elf => "elf_gd", @@ -314,18 +306,17 @@ flags_builder.set("enable_simd", "true").unwrap(); + flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); + use rustc_session::config::OptLevel; match sess.opts.optimize { OptLevel::No => { flags_builder.set("opt_level", "none").unwrap(); } OptLevel::Less | OptLevel::Default => {} - OptLevel::Aggressive => { + OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { flags_builder.set("opt_level", "speed_and_size").unwrap(); } - OptLevel::Size | OptLevel::SizeMin => { - sess.warn("Optimizing for size is not supported. Just ignoring the request"); - } } let flags = settings::Flags::new(flags_builder); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/linkage.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/linkage.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/linkage.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/linkage.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,8 +6,10 @@ mono_item: MonoItem<'_>, linkage: RLinkage, visibility: Visibility, + is_compiler_builtins: bool, ) -> Linkage { match (linkage, visibility) { + (RLinkage::External, Visibility::Default) if is_compiler_builtins => Linkage::Hidden, (RLinkage::External, Visibility::Default) => Linkage::Export, (RLinkage::Internal, Visibility::Default) => Linkage::Local, (RLinkage::External, Visibility::Hidden) => Linkage::Hidden, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/main_shim.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/main_shim.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/main_shim.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/main_shim.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,4 @@ +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_hir::LangItem; use rustc_session::config::EntryFnType; @@ -12,7 +13,7 @@ ) { let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) { Some((def_id, entry_ty)) => ( - def_id.to_def_id(), + def_id, match entry_ty { EntryFnType::Main => true, EntryFnType::Start => false, @@ -100,12 +101,8 @@ bcx.seal_all_blocks(); bcx.finalize(); } - m.define_function( - cmain_func_id, - &mut ctx, - &mut cranelift_codegen::binemit::NullTrapSink {}, - ) - .unwrap(); + m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) + .unwrap(); unwind_context.add_function(cmain_func_id, &ctx, m.isa()); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/metadata.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/metadata.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/metadata.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/metadata.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,10 +1,10 @@ //! Reading and writing of the rustc metadata for rlibs and dylibs -use std::convert::TryFrom; use std::fs::File; use std::path::Path; use rustc_codegen_ssa::METADATA_FILENAME; +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; @@ -17,38 +17,43 @@ pub(crate) struct CraneliftMetadataLoader; +fn load_metadata_with( + path: &Path, + f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, +) -> Result { + let file = File::open(path).map_err(|e| format!("{:?}", e))?; + let data = unsafe { Mmap::map(file) }.map_err(|e| format!("{:?}", e))?; + let metadata = OwningRef::new(data).try_map(f)?; + return Ok(rustc_erase_owner!(metadata.map_owner_box())); +} + impl MetadataLoader for CraneliftMetadataLoader { fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result { - let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?); - // Iterate over all entries in the archive: - while let Some(entry_result) = archive.next_entry() { - let mut entry = entry_result.map_err(|e| format!("{:?}", e))?; - if entry.header().identifier() == METADATA_FILENAME.as_bytes() { - let mut buf = Vec::with_capacity( - usize::try_from(entry.header().size()) - .expect("Rlib metadata file too big to load into memory."), - ); - ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?; - let buf: OwningRef, [u8]> = OwningRef::new(buf); - return Ok(rustc_erase_owner!(buf.map_owner_box())); + load_metadata_with(path, |data| { + let archive = object::read::archive::ArchiveFile::parse(&*data) + .map_err(|e| format!("{:?}", e))?; + + for entry_result in archive.members() { + let entry = entry_result.map_err(|e| format!("{:?}", e))?; + if entry.name() == METADATA_FILENAME.as_bytes() { + return Ok(entry.data()); + } } - } - Err("couldn't find metadata entry".to_string()) + Err("couldn't find metadata entry".to_string()) + }) } fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result { use object::{Object, ObjectSection}; - let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?; - let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?; - let buf = file - .section_by_name(".rustc") - .ok_or("no .rustc section")? - .data() - .map_err(|e| format!("failed to read .rustc section: {:?}", e))? - .to_owned(); - let buf: OwningRef, [u8]> = OwningRef::new(buf); - Ok(rustc_erase_owner!(buf.map_owner_box())) + + load_metadata_with(path, |data| { + let file = object::File::parse(&data).map_err(|e| format!("parse: {:?}", e))?; + file.section_by_name(".rustc") + .ok_or("no .rustc section")? + .data() + .map_err(|e| format!("failed to read .rustc section: {:?}", e)) + }) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/num.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/num.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/num.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/num.rs 2021-06-17 03:53:50.000000000 +0000 @@ -166,13 +166,11 @@ BinOp::Shl => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); fx.bcx.ins().ishl(lhs, actual_shift) } BinOp::Shr => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); if signed { fx.bcx.ins().sshr(lhs, actual_shift) } else { @@ -387,7 +385,7 @@ let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); - return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs); + codegen_compare_bin_op(fx, bin_op, false, lhs, rhs) } BinOp::Offset => { let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty; @@ -396,10 +394,10 @@ let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64); let base_val = base.load_scalar(fx); let res = fx.bcx.ins().iadd(base_val, ptr_diff); - return CValue::by_val(res, base.layout()); + CValue::by_val(res, base.layout()) } _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), - }; + } } else { let (lhs_ptr, lhs_extra) = in_lhs.load_scalar_pair(fx); let (rhs_ptr, rhs_extra) = in_rhs.load_scalar_pair(fx); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs 2021-06-17 03:53:50.000000000 +0000 @@ -181,7 +181,6 @@ pub(super) fn optimize_function( ctx: &mut Context, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] clif_comments: &mut crate::pretty_clif::CommentWriter, ) { combine_stack_addr_with_load_store(&mut ctx.func); @@ -192,8 +191,7 @@ remove_unused_stack_addr_and_stack_load(&mut opt_ctx); - #[cfg(debug_assertions)] - { + if clif_comments.enabled() { for (&OrdStackSlot(stack_slot), usage) in &opt_ctx.stack_slot_usage_map { clif_comments.add_comment(stack_slot, format!("used by: {:?}", usage)); } @@ -209,25 +207,27 @@ for load in users.stack_load.clone().into_iter() { let potential_stores = users.potential_stores_for_load(&opt_ctx.ctx, load); - #[cfg(debug_assertions)] - for &store in &potential_stores { - clif_comments.add_comment( - load, - format!( - "Potential store -> load forwarding {} -> {} ({:?}, {:?})", - opt_ctx.ctx.func.dfg.display_inst(store, None), - opt_ctx.ctx.func.dfg.display_inst(load, None), - spatial_overlap(&opt_ctx.ctx.func, store, load), - temporal_order(&opt_ctx.ctx, store, load), - ), - ); + if clif_comments.enabled() { + for &store in &potential_stores { + clif_comments.add_comment( + load, + format!( + "Potential store -> load forwarding {} -> {} ({:?}, {:?})", + opt_ctx.ctx.func.dfg.display_inst(store, None), + opt_ctx.ctx.func.dfg.display_inst(load, None), + spatial_overlap(&opt_ctx.ctx.func, store, load), + temporal_order(&opt_ctx.ctx, store, load), + ), + ); + } } match *potential_stores { [] => { - #[cfg(debug_assertions)] - clif_comments - .add_comment(load, "[BUG?] Reading uninitialized memory".to_string()); + if clif_comments.enabled() { + clif_comments + .add_comment(load, "[BUG?] Reading uninitialized memory".to_string()); + } } [store] if spatial_overlap(&opt_ctx.ctx.func, store, load) == SpatialOverlap::Full @@ -237,9 +237,12 @@ // Only one store could have been the origin of the value. let stored_value = opt_ctx.ctx.func.dfg.inst_args(store)[0]; - #[cfg(debug_assertions)] - clif_comments - .add_comment(load, format!("Store to load forward {} -> {}", store, load)); + if clif_comments.enabled() { + clif_comments.add_comment( + load, + format!("Store to load forward {} -> {}", store, load), + ); + } users.change_load_to_alias(&mut opt_ctx.ctx.func, load, stored_value); } @@ -250,33 +253,35 @@ for store in users.stack_store.clone().into_iter() { let potential_loads = users.potential_loads_of_store(&opt_ctx.ctx, store); - #[cfg(debug_assertions)] - for &load in &potential_loads { - clif_comments.add_comment( - store, - format!( - "Potential load from store {} <- {} ({:?}, {:?})", - opt_ctx.ctx.func.dfg.display_inst(load, None), - opt_ctx.ctx.func.dfg.display_inst(store, None), - spatial_overlap(&opt_ctx.ctx.func, store, load), - temporal_order(&opt_ctx.ctx, store, load), - ), - ); + if clif_comments.enabled() { + for &load in &potential_loads { + clif_comments.add_comment( + store, + format!( + "Potential load from store {} <- {} ({:?}, {:?})", + opt_ctx.ctx.func.dfg.display_inst(load, None), + opt_ctx.ctx.func.dfg.display_inst(store, None), + spatial_overlap(&opt_ctx.ctx.func, store, load), + temporal_order(&opt_ctx.ctx, store, load), + ), + ); + } } if potential_loads.is_empty() { // Never loaded; can safely remove all stores and the stack slot. // FIXME also remove stores when there is always a next store before a load. - #[cfg(debug_assertions)] - clif_comments.add_comment( - store, - format!( - "Remove dead stack store {} of {}", - opt_ctx.ctx.func.dfg.display_inst(store, None), - stack_slot.0 - ), - ); + if clif_comments.enabled() { + clif_comments.add_comment( + store, + format!( + "Remove dead stack store {} of {}", + opt_ctx.ctx.func.dfg.display_inst(store, None), + stack_slot.0 + ), + ); + } users.remove_dead_store(&mut opt_ctx.ctx.func, store); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pointer.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pointer.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pointer.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pointer.rs 2021-06-17 03:53:50.000000000 +0000 @@ -39,8 +39,7 @@ Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } } - #[cfg(debug_assertions)] - pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) { + pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) { (self.base, self.offset) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/pretty_clif.rs 2021-06-17 03:53:50.000000000 +0000 @@ -69,13 +69,15 @@ #[derive(Debug)] pub(crate) struct CommentWriter { + enabled: bool, global_comments: Vec, entity_comments: FxHashMap, } impl CommentWriter { pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - let global_comments = if cfg!(debug_assertions) { + let enabled = should_write_ir(tcx); + let global_comments = if enabled { vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), @@ -86,13 +88,17 @@ vec![] }; - CommentWriter { global_comments, entity_comments: FxHashMap::default() } + CommentWriter { enabled, global_comments, entity_comments: FxHashMap::default() } } } -#[cfg(debug_assertions)] impl CommentWriter { + pub(crate) fn enabled(&self) -> bool { + self.enabled + } + pub(crate) fn add_global_comment>(&mut self, comment: S) { + debug_assert!(self.enabled); self.global_comments.push(comment.into()); } @@ -101,6 +107,8 @@ entity: E, comment: S, ) { + debug_assert!(self.enabled); + use std::collections::hash_map::Entry; match self.entity_comments.entry(entity.into()) { Entry::Occupied(mut occ) => { @@ -179,7 +187,6 @@ } } -#[cfg(debug_assertions)] impl FunctionCx<'_, '_, '_> { pub(crate) fn add_global_comment>(&mut self, comment: S) { self.clif_comments.add_global_comment(comment); @@ -198,8 +205,8 @@ tcx.sess.opts.output_types.contains_key(&OutputType::LlvmAssembly) } -pub(crate) fn write_ir_file<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn write_ir_file( + tcx: TyCtxt<'_>, name: &str, write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>, ) { @@ -217,10 +224,7 @@ let clif_file_name = clif_output_dir.join(name); - let res: std::io::Result<()> = try { - let mut file = std::fs::File::create(clif_file_name)?; - write(&mut file)?; - }; + let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file)); if let Err(err) = res { tcx.sess.warn(&format!("error writing ir file: {}", err)); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/trap.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/trap.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/trap.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/trap.rs 2021-06-17 03:53:50.000000000 +0000 @@ -17,8 +17,7 @@ ) .unwrap(); let puts = fx.cx.module.declare_func_in_func(puts, &mut fx.bcx.func); - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { fx.add_comment(puts, "puts"); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/value_and_place.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,7 +2,6 @@ use crate::prelude::*; -use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; fn codegen_field<'tcx>( @@ -414,7 +413,7 @@ self, fx: &mut FunctionCx<'_, '_, 'tcx>, from: CValue<'tcx>, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] method: &'static str, + method: &'static str, ) { fn transmute_value<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -462,8 +461,7 @@ assert_eq!(self.layout().size, from.layout().size); - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { use cranelift_codegen::cursor::{Cursor, CursorPosition}; let cur_block = match fx.bcx.cursor().position() { CursorPosition::After(block) => block, @@ -707,6 +705,19 @@ } // dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed } + (&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b)) + if adt_def_a.did == adt_def_b.did => + { + let mut types_a = substs_a.types(); + let mut types_b = substs_b.types(); + loop { + match (types_a.next(), types_b.next()) { + (Some(a), Some(b)) => assert_assignable(fx, a, b), + (None, None) => return, + (Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty), + } + } + } _ => { assert_eq!( from_ty, to_ty, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/vtable.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/vtable.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/vtable.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/src/vtable.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ //! Codegen vtables and vtable accesses. //! -//! See librustc_codegen_llvm/meth.rs for reference +//! See `rustc_codegen_ssa/src/meth.rs` for reference. // FIXME dedup this logic between miri, cg_llvm and cg_clif use crate::prelude::*; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_cranelift/.vscode/settings.json 2021-06-17 03:53:50.000000000 +0000 @@ -2,7 +2,7 @@ // source for rustc_* is not included in the rust-src component; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "macro-error"], "rust-analyzer.assist.importMergeBehavior": "last", - "rust-analyzer.cargo.loadOutDirsFromCheck": true, + "rust-analyzer.cargo.runBuildScripts": true, "rust-analyzer.linkedProjects": [ "./Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/abi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/abi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/abi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/abi.rs 2021-06-17 03:53:50.000000000 +0000 @@ -41,12 +41,23 @@ } pub trait ArgAttributesExt { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value); - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value); + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ); +} + +fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool { + // While #84958 has been fixed, mutable noalias is not enabled by default + // in Rust 1.53 out of an abundance of caution. + cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(false) } impl ArgAttributesExt for ArgAttributes { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) { + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -62,6 +73,9 @@ llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_llfn(idx, llfn); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -74,7 +88,12 @@ } } - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) { + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -98,6 +117,9 @@ ); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_callsite(idx, callsite); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -419,13 +441,13 @@ let mut i = 0; let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), cx, llfn); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); @@ -480,18 +502,18 @@ // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. let mut i = 0; - let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite); + let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| { + attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), cx, callsite); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, &bx.cx, callsite); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddStructRetCallSiteAttr( callsite, @@ -517,12 +539,12 @@ } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddByValCallSiteAttr( callsite, @@ -533,22 +555,22 @@ } PassMode::Direct(ref attrs) | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { - apply(attrs); + apply(bx.cx, attrs); } PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack: _, } => { - apply(attrs); - apply(extra_attrs); + apply(bx.cx, attrs); + apply(bx.cx, extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a); - apply(b); + apply(bx.cx, a); + apply(bx.cx, b); } PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/asm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/asm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/asm.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/asm.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug}; -use rustc_span::{Pos, Span}; +use rustc_span::{Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -125,15 +125,39 @@ // Collect the types of output operands let mut constraints = vec![]; + let mut clobbers = vec![]; let mut output_types = vec![]; let mut op_idx = FxHashMap::default(); for (idx, op) in operands.iter().enumerate() { match *op { InlineAsmOperandRef::Out { reg, late, place } => { + let is_target_supported = |reg_class: InlineAsmRegClass| { + for &(_, feature) in reg_class.supported_types(asm_arch) { + if let Some(feature) = feature { + if self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + { + return true; + } + } else { + // Register class is unconditionally supported + return true; + } + } + false + }; + let mut layout = None; let ty = if let Some(ref place) = place { layout = Some(&place.layout); llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout) + } else if !is_target_supported(reg.reg_class()) { + // We turn discarded outputs into clobber constraints + // if the target feature needed by the register class is + // disabled. This is necessary otherwise LLVM will try + // to actually allocate a register for the dummy output. + assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_))); + clobbers.push(format!("~{}", reg_to_llvm(reg, None))); + continue; } else { // If the output is discarded, we don't really care what // type is used. We're just using this to tell LLVM to @@ -244,6 +268,7 @@ } } + constraints.append(&mut clobbers); if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { match asm_arch { InlineAsmArch::AArch64 | InlineAsmArch::Arm => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/attributes.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/attributes.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/attributes.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/attributes.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,9 +11,10 @@ use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::config::{OptLevel, SanitizerSet}; +use rustc_session::config::OptLevel; use rustc_session::Session; -use rustc_target::spec::StackProbeType; +use rustc_target::spec::abi::Abi; +use rustc_target::spec::{SanitizerSet, StackProbeType}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -254,6 +255,7 @@ attributes::emit_uwtable(llfn, true); } + // FIXME: none of these three functions interact with source level attributes. set_frame_pointer_elimination(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); @@ -289,7 +291,7 @@ // The target doesn't care; the subtarget reads our attribute. apply_tune_cpu_attr(cx, llfn); - let function_features = codegen_fn_attrs + let mut function_features = codegen_fn_attrs .target_features .iter() .map(|f| { @@ -301,23 +303,10 @@ InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) .collect::>(); - if !function_features.is_empty() { - let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); - global_features.extend(function_features.into_iter()); - let features = global_features.join(","); - let val = CString::new(features).unwrap(); - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("target-features"), - &val, - ); - } - // Note that currently the `wasm-import-module` doesn't do anything, but - // eventually LLVM 7 should read this and ferry the appropriate import - // module to the output file. - if cx.tcx.sess.target.arch == "wasm32" { + if cx.tcx.sess.target.is_like_wasm { + // If this function is an import from the environment but the wasm + // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { llvm::AddFunctionAttrStringValue( llfn, @@ -336,6 +325,30 @@ &name, ); } + + // The `"wasm"` abi on wasm targets automatically enables the + // `+multivalue` feature because the purpose of the wasm abi is to match + // the WebAssembly specification, which has this feature. This won't be + // needed when LLVM enables this `multivalue` feature by default. + if !cx.tcx.is_closure(instance.def_id()) { + let abi = cx.tcx.fn_sig(instance.def_id()).abi(); + if abi == Abi::Wasm { + function_features.push("+multivalue".to_string()); + } + } + } + + if !function_features.is_empty() { + let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); + global_features.extend(function_features.into_iter()); + let features = global_features.join(","); + let val = CString::new(features).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("target-features"), + &val, + ); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/lto.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/lto.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/lto.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/lto.rs 2021-06-17 03:53:50.000000000 +0000 @@ -24,6 +24,7 @@ use std::ffi::{CStr, CString}; use std::fs::File; use std::io; +use std::iter; use std::path::Path; use std::ptr; use std::slice; @@ -916,9 +917,7 @@ modules: &[llvm::ThinLTOModule], names: &[CString], ) -> Self { - let keys = modules - .iter() - .zip(names.iter()) + let keys = iter::zip(modules, names) .map(|(module, name)| { let key = build_string(|rust_str| unsafe { llvm::LLVMRustComputeLTOCacheKey(rust_str, module.identifier, data.0); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/write.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/write.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/write.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/back/write.rs 2021-06-17 03:53:50.000000000 +0000 @@ -23,11 +23,11 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath}; +use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; -use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo}; +use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo}; use tracing::debug; use libc::{c_char, c_int, c_uint, c_void, size_t}; @@ -170,10 +170,7 @@ // On the wasm target once the `atomics` feature is enabled that means that // we're no longer single-threaded, or otherwise we don't want LLVM to // lower atomic operations to single-threaded operations. - if singlethread - && sess.target.llvm_target.contains("wasm32") - && sess.target_features.contains(&sym::atomics) - { + if singlethread && sess.target.is_like_wasm && sess.target_features.contains(&sym::atomics) { singlethread = false; } @@ -548,6 +545,15 @@ llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap()); continue; } + if pass_name == "insert-gcov-profiling" || pass_name == "instrprof" { + // Instrumentation must be inserted before optimization, + // otherwise LLVM may optimize some functions away which + // breaks llvm-cov. + // + // This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp. + llvm::LLVMRustAddPass(mpm, find_pass(pass_name).unwrap()); + continue; + } if let Some(pass) = find_pass(pass_name) { extra_passes.push(pass); @@ -1041,7 +1047,7 @@ // thresholds copied from clang. match (opt_level, opt_size, inline_threshold) { (.., Some(t)) => { - llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32); + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t); } (llvm::CodeGenOptLevel::Aggressive, ..) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/base.rs 2021-06-17 03:53:50.000000000 +0000 @@ -32,8 +32,9 @@ use rustc_middle::middle::exported_symbols; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{DebugInfo, SanitizerSet}; +use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; +use rustc_target::spec::SanitizerSet; use std::ffi::CString; use std::time::Instant; @@ -143,7 +144,7 @@ // Finalize code coverage by injecting the coverage map. Note, the coverage map will // also be added to the `llvm.used` variable, created next. - if cx.sess().opts.debugging_opts.instrument_coverage { + if cx.sess().instrument_coverage() { cx.coverageinfo_finalize(); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/builder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/builder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/builder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/builder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,6 +2,7 @@ use crate::context::CodegenCx; use crate::llvm::{self, BasicBlock, False}; use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -16,11 +17,12 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; +use std::iter; use std::ops::{Deref, Range}; use std::ptr; use tracing::debug; @@ -260,7 +262,7 @@ fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -268,7 +270,7 @@ fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -276,7 +278,7 @@ fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -284,7 +286,7 @@ fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -292,7 +294,7 @@ fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -668,81 +670,47 @@ } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } + None } fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.signed.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.signed.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.signed.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.signed.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } - None - } - fn fptosui_may_trap(&self, val: &'ll Value, dest_ty: &'ll Type) -> bool { - // Most of the time we'll be generating the `fptosi` or `fptoui` - // instruction for floating-point-to-integer conversions. These - // instructions by definition in LLVM do not trap. For the WebAssembly - // target, however, we'll lower in some cases to intrinsic calls instead - // which may trap. If we detect that this is a situation where we'll be - // using the intrinsics then we report that the call map trap, which - // callers might need to handle. - if !self.wasm_and_missing_nontrapping_fptoint() { - return false; - } - let src_ty = self.cx.val_ty(val); - let float_width = self.cx.float_width(src_ty); - let int_width = self.cx.int_width(dest_ty); - matches!((int_width, float_width), (32, 32) | (32, 64) | (64, 32) | (64, 64)) + None } fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - // When we can, use the native wasm intrinsics which have tighter - // codegen. Note that this has a semantic difference in that the - // intrinsic can trap whereas `fptoui` never traps. That difference, - // however, is handled by `fptosui_may_trap` above. + // On WebAssembly the `fptoui` and `fptosi` instructions currently have + // poor codegen. The reason for this is that the corresponding wasm + // instructions, `i32.trunc_f32_s` for example, will trap when the float + // is out-of-bounds, infinity, or nan. This means that LLVM + // automatically inserts control flow around `fptoui` and `fptosi` + // because the LLVM instruction `fptoui` is defined as producing a + // poison value, not having UB on out-of-bounds values. // - // Note that we skip the wasm intrinsics for vector types where `fptoui` - // must be used instead. - if self.wasm_and_missing_nontrapping_fptoint() { + // This method, however, is only used with non-saturating casts that + // have UB on out-of-bounds values. This means that it's ok if we use + // the raw wasm instruction since out-of-bounds values can do whatever + // we like. To ensure that LLVM picks the right instruction we choose + // the raw wasm intrinsic functions which avoid LLVM inserting all the + // other control flow automatically. + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -764,7 +732,8 @@ } fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - if self.wasm_and_missing_nontrapping_fptoint() { + // see `fptoui` above for why wasm is different here + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -1241,14 +1210,14 @@ pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1281,7 +1250,7 @@ unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1289,7 +1258,7 @@ unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1352,18 +1321,14 @@ let param_tys = self.cx.func_params_types(fn_ty); - let all_args_match = param_tys - .iter() - .zip(args.iter().map(|&v| self.val_ty(v))) + let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.val_ty(v))) .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty); if all_args_match { return Cow::Borrowed(args); } - let casted_args: Vec<_> = param_tys - .into_iter() - .zip(args.iter()) + let casted_args: Vec<_> = iter::zip(param_tys, args) .enumerate() .map(|(i, (expected_ty, &actual_val))| { let actual_ty = self.val_ty(actual_val); @@ -1423,8 +1388,11 @@ } } - fn wasm_and_missing_nontrapping_fptoint(&self) -> bool { - self.sess().target.arch == "wasm32" - && !self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) + fn fptoint_sat_broken_in_llvm(&self) -> bool { + match self.tcx.sess.target.arch.as_str() { + // FIXME - https://bugs.llvm.org/show_bug.cgi?id=50083 + "riscv64" => llvm_util::get_version() < (13, 0, 0), + _ => false, + } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/callee.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/callee.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/callee.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/callee.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_target::spec::RelocModel; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -170,17 +171,19 @@ } } } - } - // MinGW: For backward compatibility we rely on the linker to decide whether it - // should use dllimport for functions. - if cx.use_dll_storage_attrs - && tcx.is_dllimport_foreign_item(instance_def_id) - && tcx.sess.target.env != "gnu" - { - unsafe { + // MinGW: For backward compatibility we rely on the linker to decide whether it + // should use dllimport for functions. + if cx.use_dll_storage_attrs + && tcx.is_dllimport_foreign_item(instance_def_id) + && tcx.sess.target.env != "gnu" + { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); } + + if cx.tcx.sess.relocation_model() == RelocModel::Static { + llvm::LLVMRustSetDSOLocal(llfn, true); + } } llfn diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/context.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/context.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/context.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/context.rs 2021-06-17 03:53:50.000000000 +0000 @@ -79,7 +79,7 @@ pub pointee_infos: RefCell, Size), Option>>, pub isize_ty: &'ll Type, - pub coverage_cx: Option>, + pub coverage_cx: Option>, pub dbg_cx: Option>, eh_personality: Cell>, @@ -101,10 +101,6 @@ } } -fn strip_x86_address_spaces(data_layout: String) -> String { - data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-") -} - fn strip_powerpc64_vectors(data_layout: String) -> String { data_layout.replace("-v256:256:256-v512:512:512", "") } @@ -119,11 +115,6 @@ let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let mut target_data_layout = sess.target.data_layout.clone(); - if llvm_util::get_version() < (10, 0, 0) - && (sess.target.arch == "x86" || sess.target.arch == "x86_64") - { - target_data_layout = strip_x86_address_spaces(target_data_layout); - } if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { target_data_layout = strip_powerpc64_vectors(target_data_layout); } @@ -280,7 +271,7 @@ let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - let coverage_cx = if tcx.sess.opts.debugging_opts.instrument_coverage { + let coverage_cx = if tcx.sess.instrument_coverage() { let covctx = coverageinfo::CrateCoverageContext::new(); Some(covctx) } else { @@ -331,7 +322,7 @@ } #[inline] - pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'tcx>> { + pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } } @@ -512,14 +503,6 @@ let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f64", fn(t_f64) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64); ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64); @@ -529,6 +512,28 @@ ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64); ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptosi.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f64", fn(t_f64) -> t_i128); + + ifn!("llvm.fptoui.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptoui.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f64", fn(t_f64) -> t_i128); + ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); @@ -712,7 +717,7 @@ ifn!("llvm.va_end", fn(i8p) -> void); ifn!("llvm.va_copy", fn(i8p, i8p) -> void); - if self.sess().opts.debugging_opts.instrument_coverage { + if self.sess().instrument_coverage() { ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,13 +3,13 @@ use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, FunctionCoverage}; -use rustc_codegen_ssa::traits::ConstMethods; +use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; +use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_llvm::RustString; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::CodeRegion; -use rustc_middle::ty::{Instance, TyCtxt}; use rustc_span::Symbol; use std::ffi::CString; @@ -20,16 +20,17 @@ /// /// 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 current (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. +/// 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. /// /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with -/// version 3. Clang's implementation of Coverage Map generation was referenced when implementing -/// this Rust version, and though the format documentation is very explicit and detailed, some -/// undocumented details in Clang's implementation (that may or may not be important) were also -/// replicated for Rust's Coverage Map. +/// the same version. Clang's implementation of Coverage Map generation was referenced when +/// implementing this Rust version, and though the format documentation is very explicit and +/// detailed, some undocumented details in Clang's implementation (that may or may not be important) +/// were also replicated for Rust's Coverage Map. 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. let version = coverageinfo::mapping_version(); @@ -39,17 +40,24 @@ debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); - let mut function_coverage_map = match cx.coverage_context() { + // In order to show that unused functions have coverage counts of zero (0), LLVM requires the + // functions exist. Generate synthetic functions with a (required) single counter, and add the + // MIR `Coverage` code regions to the `function_coverage_map`, before calling + // `ctx.take_function_coverage_map()`. + if !tcx.sess.instrument_coverage_except_unused_functions() { + add_unused_functions(cx); + } + + let function_coverage_map = match cx.coverage_context() { Some(ctx) => ctx.take_function_coverage_map(), None => return, }; + if function_coverage_map.is_empty() { // This module has no functions with coverage instrumentation return; } - add_unreachable_coverage(tcx, &mut function_coverage_map); - let mut mapgen = CoverageMapGenerator::new(); // Encode coverage mappings and generate function records @@ -57,7 +65,8 @@ for (instance, function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); let mangled_function_name = tcx.symbol_name(instance).to_string(); - let function_source_hash = function_coverage.source_hash(); + let source_hash = function_coverage.source_hash(); + let is_used = function_coverage.is_used(); let (expressions, counter_regions) = function_coverage.get_expressions_and_counter_regions(); @@ -69,7 +78,7 @@ "Every `FunctionCoverage` should have at least one counter" ); - function_data.push((mangled_function_name, function_source_hash, coverage_mapping_buffer)); + function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer)); } // Encode all filenames referenced by counters/expressions in this module @@ -84,13 +93,14 @@ // Generate the LLVM IR representation of the coverage map and store it in a well-known global let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val); - for (mangled_function_name, function_source_hash, coverage_mapping_buffer) in function_data { + for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data { save_function_record( cx, mangled_function_name, - function_source_hash, + source_hash, filenames_ref, coverage_mapping_buffer, + is_used, ); } @@ -201,9 +211,10 @@ fn save_function_record( cx: &CodegenCx<'ll, 'tcx>, mangled_function_name: String, - function_source_hash: u64, + source_hash: u64, filenames_ref: u64, coverage_mapping_buffer: Vec, + is_used: bool, ) { // Concatenate the encoded coverage mappings let coverage_mapping_size = coverage_mapping_buffer.len(); @@ -212,128 +223,124 @@ let func_name_hash = coverageinfo::hash_str(&mangled_function_name); let func_name_hash_val = cx.const_u64(func_name_hash); let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32); - let func_hash_val = cx.const_u64(function_source_hash); + let source_hash_val = cx.const_u64(source_hash); let filenames_ref_val = cx.const_u64(filenames_ref); let func_record_val = cx.const_struct( &[ func_name_hash_val, coverage_mapping_size_val, - func_hash_val, + source_hash_val, filenames_ref_val, coverage_mapping_val, ], /*packed=*/ true, ); - // At the present time, the coverage map for Rust assumes every instrumented function `is_used`. - // Note that Clang marks functions as "unused" in `CodeGenPGO::emitEmptyCounterMapping`. (See: - // https://github.com/rust-lang/llvm-project/blob/de02a75e398415bad4df27b4547c25b896c8bf3b/clang%2Flib%2FCodeGen%2FCodeGenPGO.cpp#L877-L878 - // for example.) - // - // It's not yet clear if or how this may be applied to Rust in the future, but the `is_used` - // argument is available and handled similarly. - let is_used = true; coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used); } /// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for /// the functions that went through codegen; such as public functions and "used" functions /// (functions referenced by other "used" or public items). Any other functions considered unused, -/// or "Unreachable" were still parsed and processed through the MIR stage. +/// or "Unreachable", were still parsed and processed through the MIR stage, but were not +/// codegenned. (Note that `-Clink-dead-code` can force some unused code to be codegenned, but +/// that flag is known to cause other errors, when combined with `-Z instrument-coverage`; and +/// `-Clink-dead-code` will not generate code for unused generic functions.) /// -/// We can find the unreachable functions by the set difference of all MIR `DefId`s (`tcx` query -/// `mir_keys`) minus the codegenned `DefId`s (`tcx` query `collect_and_partition_mono_items`). +/// We can find the unused functions (including generic functions) by the set difference of all MIR +/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query +/// `collect_and_partition_mono_items`). /// /// *HOWEVER* the codegenned `DefId`s are partitioned across multiple `CodegenUnit`s (CGUs), and /// this function is processing a `function_coverage_map` for the functions (`Instance`/`DefId`) -/// allocated to only one of those CGUs. We must NOT inject any "Unreachable" functions's -/// `CodeRegion`s more than once, so we have to pick which CGU's `function_coverage_map` to add -/// each "Unreachable" function to. -/// -/// Some constraints: -/// -/// 1. The file name of an "Unreachable" function must match the file name of the existing -/// codegenned (covered) function to which the unreachable code regions will be added. -/// 2. The function to which the unreachable code regions will be added must not be a generic -/// function (must not have type parameters) because the coverage tools will get confused -/// if the codegenned function has more than one instantiation and additional `CodeRegion`s -/// attached to only one of those instantiations. -fn add_unreachable_coverage<'tcx>( - tcx: TyCtxt<'tcx>, - function_coverage_map: &mut FxHashMap, FunctionCoverage<'tcx>>, -) { +/// allocated to only one of those CGUs. We must NOT inject any unused functions's `CodeRegion`s +/// more than once, so we have to pick a CGUs `function_coverage_map` into which the unused +/// function will be inserted. +fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { + let tcx = cx.tcx; + // FIXME(#79622): Can this solution be simplified and/or improved? Are there other sources // of compiler state data that might help (or better sources that could be exposed, but // aren't yet)? - // Note: If the crate *only* defines generic functions, there are no codegenerated non-generic - // functions to add any unreachable code to. In this case, the unreachable code regions will - // have no coverage, instead of having coverage with zero executions. - // - // This is probably still an improvement over Clang, which does not generate any coverage - // for uninstantiated template functions. + let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics(); - let has_non_generic_def_ids = - function_coverage_map.keys().any(|instance| instance.def.attrs(tcx).len() == 0); - - if !has_non_generic_def_ids { - // There are no non-generic functions to add unreachable `CodeRegion`s to - return; - } - - let all_def_ids: DefIdSet = - tcx.mir_keys(LOCAL_CRATE).iter().map(|local_def_id| local_def_id.to_def_id()).collect(); + let all_def_ids: DefIdSet = tcx + .mir_keys(LOCAL_CRATE) + .iter() + .filter_map(|local_def_id| { + let def_id = local_def_id.to_def_id(); + if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) { + return None; + } + Some(local_def_id.to_def_id()) + }) + .collect(); let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE); - let mut unreachable_def_ids_by_file: FxHashMap> = FxHashMap::default(); + let mut unused_def_ids_by_file: FxHashMap> = FxHashMap::default(); for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) { - // Make sure the non-codegenned (unreachable) function has a file_name + let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id); + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + continue; + } + // Make sure the non-codegenned (unused) function has a file_name if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) { - let def_ids = unreachable_def_ids_by_file - .entry(*non_codegenned_file_name) - .or_insert_with(Vec::new); + let def_ids = + unused_def_ids_by_file.entry(*non_codegenned_file_name).or_insert_with(Vec::new); def_ids.push(non_codegenned_def_id); } } - if unreachable_def_ids_by_file.is_empty() { - // There are no unreachable functions with file names to add (in any CGU) + if unused_def_ids_by_file.is_empty() { + // There are no unused functions with file names to add (in any CGU) return; } - // Since there may be multiple `CodegenUnit`s, some codegenned_def_ids may be codegenned in a - // different CGU, and will be added to the function_coverage_map for each CGU. Determine which - // function_coverage_map has the responsibility for publishing unreachable coverage - // based on file name: + // Each `CodegenUnit` (CGU) has its own function_coverage_map, and generates a specific binary + // with its own coverage map. + // + // Each covered function `Instance` can be included in only one coverage map, produced from a + // specific function_coverage_map, from a specific CGU. + // + // Since unused functions did not generate code, they are not associated with any CGU yet. // - // For each covered file name, sort ONLY the non-generic codegenned_def_ids, and if - // covered_def_ids.contains(the first def_id) for a given file_name, add the unreachable code - // region in this function_coverage_map. Otherwise, ignore it and assume another CGU's - // function_coverage_map will be adding it (because it will be first for one, and only one, - // of them). + // To avoid injecting the unused functions in multiple coverage maps (for multiple CGUs) + // determine which function_coverage_map has the responsibility for publishing unreachable + // coverage, based on file name: For each unused function, find the CGU that generates the + // first function (based on sorted `DefId`) from the same file. + // + // Add a new `FunctionCoverage` to the `function_coverage_map`, with unreachable code regions + // for each region in it's MIR. + + // Convert the `HashSet` of `codegenned_def_ids` to a sortable vector, and sort them. let mut sorted_codegenned_def_ids: Vec = codegenned_def_ids.iter().map(|def_id| *def_id).collect(); sorted_codegenned_def_ids.sort_unstable(); let mut first_covered_def_id_by_file: FxHashMap = FxHashMap::default(); for &def_id in sorted_codegenned_def_ids.iter() { - // Only consider non-generic functions, to potentially add unreachable code regions - if tcx.generics_of(def_id).count() == 0 { - if let Some(covered_file_name) = tcx.covered_file_name(def_id) { - // Only add files known to have unreachable functions - if unreachable_def_ids_by_file.contains_key(covered_file_name) { - first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id); - } + if let Some(covered_file_name) = tcx.covered_file_name(def_id) { + // Only add files known to have unused functions + if unused_def_ids_by_file.contains_key(covered_file_name) { + first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id); } } } // Get the set of def_ids with coverage regions, known by *this* CoverageContext. - let cgu_covered_def_ids: DefIdSet = - function_coverage_map.keys().map(|instance| instance.def.def_id()).collect(); + let cgu_covered_def_ids: DefIdSet = match cx.coverage_context() { + Some(ctx) => ctx + .function_coverage_map + .borrow() + .keys() + .map(|&instance| instance.def.def_id()) + .collect(), + None => return, + }; - let mut cgu_covered_files: FxHashSet = first_covered_def_id_by_file + let cgu_covered_files: FxHashSet = first_covered_def_id_by_file .iter() .filter_map( |(&file_name, def_id)| { @@ -342,49 +349,13 @@ ) .collect(); - // Find the first covered, non-generic function (instance) for each cgu_covered_file. Take the - // unreachable code regions for that file, and add them to the function. - // - // There are three `for` loops here, but (a) the lists have already been reduced to the minimum - // required values, the lists are further reduced (by `remove()` calls) when elements are no - // longer needed, and there are several opportunities to branch out of loops early. - for (instance, function_coverage) in function_coverage_map.iter_mut() { - if instance.def.attrs(tcx).len() > 0 { - continue; - } - // The covered function is not generic... - let covered_def_id = instance.def.def_id(); - if let Some(covered_file_name) = tcx.covered_file_name(covered_def_id) { - if !cgu_covered_files.remove(&covered_file_name) { - continue; - } - // The covered function's file is one of the files with unreachable code regions, so - // all of the unreachable code regions for this file will be added to this function. - for def_id in - unreachable_def_ids_by_file.remove(&covered_file_name).into_iter().flatten() - { - // Note, this loop adds an unreachable code regions for each MIR-derived region. - // Alternatively, we could add a single code region for the maximum span of all - // code regions here. - // - // Observed downsides of this approach are: - // - // 1. The coverage results will appear inconsistent compared with the same (or - // similar) code in a function that is reached. - // 2. If the function is unreachable from one crate but reachable when compiling - // another referencing crate (such as a cross-crate reference to a - // generic function or inlined function), actual coverage regions overlaid - // on a single larger code span of `Zero` coverage can appear confusing or - // wrong. Chaning the unreachable coverage from a `code_region` to a - // `gap_region` can help, but still can look odd with `0` line counts for - // lines between executed (> 0) lines (such as for blank lines or comments). - for ®ion in tcx.covered_code_regions(def_id) { - function_coverage.add_unreachable_region(region.clone()); - } - } - if cgu_covered_files.is_empty() { - break; - } + // For each file for which this CGU is responsible for adding unused function coverage, + // get the `def_id`s for each unused function (if any), define a synthetic function with a + // single LLVM coverage counter, and add the function's coverage `CodeRegion`s. to the + // function_coverage_map. + for covered_file_name in cgu_covered_files { + for def_id in unused_def_ids_by_file.remove(&covered_file_name).into_iter().flatten() { + cx.define_unused_fn(def_id); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,6 @@ use crate::llvm; +use crate::abi::{Abi, FnAbi}; use crate::builder::Builder; use crate::common::CodegenCx; @@ -7,33 +8,47 @@ use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage}; use rustc_codegen_ssa::traits::{ - BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods, + BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, + MiscMethods, StaticMethods, }; use rustc_data_structures::fx::FxHashMap; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_llvm::RustString; +use rustc_middle::bug; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, }; +use rustc_middle::ty; +use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; use std::cell::RefCell; use std::ffi::CString; +use std::iter; use tracing::debug; pub mod mapgen; +const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START; + const VAR_ALIGN_BYTES: usize = 8; /// A context object for maintaining all state needed by the coverageinfo module. -pub struct CrateCoverageContext<'tcx> { +pub struct CrateCoverageContext<'ll, 'tcx> { // Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell, FunctionCoverage<'tcx>>>, + pub(crate) pgo_func_name_var_map: RefCell, &'ll llvm::Value>>, } -impl<'tcx> CrateCoverageContext<'tcx> { +impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { pub fn new() -> Self { - Self { function_coverage_map: Default::default() } + Self { + function_coverage_map: Default::default(), + pgo_func_name_var_map: Default::default(), + } } pub fn take_function_coverage_map(&self) -> FxHashMap, FunctionCoverage<'tcx>> { @@ -41,23 +56,47 @@ } } -impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> { +impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn coverageinfo_finalize(&self) { mapgen::finalize(self) } -} -impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { - /// Calls llvm::createPGOFuncNameVar() with the given function instance's mangled function name. - /// The LLVM API returns an llvm::GlobalVariable containing the function name, with the specific - /// variable name and linkage required by LLVM InstrProf source-based coverage instrumentation. - fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value { - let llfn = self.cx.get_fn(instance); - let mangled_fn_name = CString::new(self.tcx.symbol_name(instance).name) - .expect("error converting function name to C string"); - unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) } + fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { + if let Some(coverage_context) = self.coverage_context() { + debug!("getting pgo_func_name_var for instance={:?}", instance); + let mut pgo_func_name_var_map = coverage_context.pgo_func_name_var_map.borrow_mut(); + pgo_func_name_var_map + .entry(instance) + .or_insert_with(|| create_pgo_func_name_var(self, instance)) + } else { + bug!("Could not get the `coverage_context`"); + } } + /// Functions with MIR-based coverage are normally codegenned _only_ if + /// called. LLVM coverage tools typically expect every function to be + /// defined (even if unused), with at least one call to LLVM intrinsic + /// `instrprof.increment`. + /// + /// Codegen a small function that will never be called, with one counter + /// that will never be incremented. + /// + /// For used/called functions, the coverageinfo was already added to the + /// `function_coverage_map` (keyed by function `Instance`) during codegen. + /// But in this case, since the unused function was _not_ previously + /// codegenned, collect the coverage `CodeRegion`s from the MIR and add + /// them. The first `CodeRegion` is used to add a single counter, with the + /// same counter ID used in the injected `instrprof.increment` intrinsic + /// call. Since the function is never called, all other `CodeRegion`s can be + /// added as `unreachable_region`s. + fn define_unused_fn(&self, def_id: DefId) { + let instance = declare_unused_fn(self, &def_id); + codegen_unused_fn_and_counter(self, instance); + add_unused_function_coverage(self, instance, def_id); + } +} + +impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -145,6 +184,100 @@ } } +fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx> { + let tcx = cx.tcx; + + let instance = Instance::new( + *def_id, + InternalSubsts::for_item(tcx, *def_id, |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }), + ); + + let llfn = cx.declare_fn( + &tcx.symbol_name(instance).name, + &FnAbi::of_fn_ptr( + cx, + ty::Binder::dummy(tcx.mk_fn_sig( + iter::once(tcx.mk_unit()), + tcx.mk_unit(), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + )), + &[], + ), + ); + + llvm::set_linkage(llfn, llvm::Linkage::WeakAnyLinkage); + llvm::set_visibility(llfn, llvm::Visibility::Hidden); + + assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none()); + + instance +} + +fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { + let llfn = cx.get_fn(instance); + let mut bx = Builder::new_block(cx, llfn, "unused_function"); + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(0); + let num_counters = bx.const_u32(1); + let index = bx.const_u32(u32::from(UNUSED_FUNCTION_COUNTER_ID)); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, + index={:?}) for unused function: {:?}", + fn_name, hash, num_counters, index, instance + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); + bx.ret_void(); +} + +fn add_unused_function_coverage( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + def_id: DefId, +) { + let tcx = cx.tcx; + + let mut function_coverage = FunctionCoverage::unused(tcx, instance); + for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() { + if index == 0 { + // Insert at least one real counter so the LLVM CoverageMappingReader will find expected + // definitions. + function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone()); + } else { + function_coverage.add_unreachable_region(code_region.clone()); + } + } + + if let Some(coverage_context) = cx.coverage_context() { + coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); + } else { + bug!("Could not get the `coverage_context`"); + } +} + +/// Calls llvm::createPGOFuncNameVar() with the given function instance's +/// mangled function name. The LLVM API returns an llvm::GlobalVariable +/// containing the function name, with the specific variable name and linkage +/// 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( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, +) -> &'ll llvm::Value { + let mangled_fn_name = CString::new(cx.tcx.symbol_name(instance).name) + .expect("error converting function name to C string"); + let llfn = cx.get_fn(instance); + unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) } +} + pub(crate) fn write_filenames_section_to_buffer<'a>( filenames: impl IntoIterator, buffer: &RustString, @@ -177,6 +310,7 @@ ); } } + pub(crate) fn hash_str(strval: &str) -> u64 { let strval = CString::new(strval).expect("null error converting hashable str to C string"); unsafe { llvm::LLVMRustCoverageHashCString(strval.as_ptr()) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.md 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.md 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,180 @@ +# Debug Info Module + +This module serves the purpose of generating debug symbols. We use LLVM's +[source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) +features for generating the debug information. The general principle is +this: + +Given the right metadata in the LLVM IR, the LLVM code generator is able to +create DWARF debug symbols for the given code. The +[metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured +much like DWARF *debugging information entries* (DIE), representing type +information such as datatype layout, function signatures, block layout, +variable location and scope information, etc. It is the purpose of this +module to generate correct metadata and insert it into the LLVM IR. + +As the exact format of metadata trees may change between different LLVM +versions, we now use LLVM +[DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) +to create metadata where possible. This will hopefully ease the adaption of +this module to future LLVM versions. + +The public API of the module is a set of functions that will insert the +correct metadata into the LLVM IR when called with the right parameters. +The module is thus driven from an outside client with functions like +`debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. + +Internally the module will try to reuse already created metadata by +utilizing a cache. The way to get a shared metadata node when needed is +thus to just call the corresponding function in this module: + + let file_metadata = file_metadata(cx, file); + +The function will take care of probing the cache for an existing node for +that exact file path. + +All private state used by the module is stored within either the +CrateDebugContext struct (owned by the CodegenCx) or the +FunctionDebugContext (owned by the FunctionCx). + +This file consists of three conceptual sections: +1. The public interface of the module +2. Module-internal metadata creation functions +3. Minor utility functions + + +## Recursive Types + +Some kinds of types, such as structs and enums can be recursive. That means +that the type definition of some type X refers to some other type which in +turn (transitively) refers to X. This introduces cycles into the type +referral graph. A naive algorithm doing an on-demand, depth-first traversal +of this graph when describing types, can get trapped in an endless loop +when it reaches such a cycle. + +For example, the following simple type for a singly-linked list... + +``` +struct List { + value: i32, + tail: Option>, +} +``` + +will generate the following callstack with a naive DFS algorithm: + +``` +describe(t = List) + describe(t = i32) + describe(t = Option>) + describe(t = Box) + describe(t = List) // at the beginning again... + ... +``` + +To break cycles like these, we use "forward declarations". That is, when +the algorithm encounters a possibly recursive type (any struct or enum), it +immediately creates a type description node and inserts it into the cache +*before* describing the members of the type. This type description is just +a stub (as type members are not described and added to it yet) but it +allows the algorithm to already refer to the type. After the stub is +inserted into the cache, the algorithm continues as before. If it now +encounters a recursive reference, it will hit the cache and does not try to +describe the type anew. + +This behavior is encapsulated in the 'RecursiveTypeDescription' enum, +which represents a kind of continuation, storing all state needed to +continue traversal at the type members after the type has been registered +with the cache. (This implementation approach might be a tad over- +engineered and may change in the future) + + +## Source Locations and Line Information + +In addition to data type descriptions the debugging information must also +allow to map machine code locations back to source code locations in order +to be useful. This functionality is also handled in this module. The +following functions allow to control source mappings: + ++ `set_source_location()` ++ `clear_source_location()` ++ `start_emitting_source_locations()` + +`set_source_location()` allows to set the current source location. All IR +instructions created after a call to this function will be linked to the +given source location, until another location is specified with +`set_source_location()` or the source location is cleared with +`clear_source_location()`. In the later case, subsequent IR instruction +will not be linked to any source location. As you can see, this is a +stateful API (mimicking the one in LLVM), so be careful with source +locations set by previous calls. It's probably best to not rely on any +specific state being present at a given point in code. + +One topic that deserves some extra attention is *function prologues*. At +the beginning of a function's machine code there are typically a few +instructions for loading argument values into allocas and checking if +there's enough stack space for the function to execute. This *prologue* is +not visible in the source code and LLVM puts a special PROLOGUE END marker +into the line table at the first non-prologue instruction of the function. +In order to find out where the prologue ends, LLVM looks for the first +instruction in the function body that is linked to a source location. So, +when generating prologue instructions we have to make sure that we don't +emit source location information until the 'real' function body begins. For +this reason, source location emission is disabled by default for any new +function being codegened and is only activated after a call to the third +function from the list above, `start_emitting_source_locations()`. This +function should be called right before regularly starting to codegen the +top-level block of the given function. + +There is one exception to the above rule: `llvm.dbg.declare` instruction +must be linked to the source location of the variable being declared. For +function parameters these `llvm.dbg.declare` instructions typically occur +in the middle of the prologue, however, they are ignored by LLVM's prologue +detection. The `create_argument_metadata()` and related functions take care +of linking the `llvm.dbg.declare` instructions to the correct source +locations even while source location emission is still disabled, so there +is no need to do anything special with source location handling here. + +## Unique Type Identification + +In order for link-time optimization to work properly, LLVM needs a unique +type identifier that tells it across compilation units which types are the +same as others. This type identifier is created by +`TypeMap::get_unique_type_id_of_type()` using the following algorithm: + +1. Primitive types have their name as ID + +2. Structs, enums and traits have a multipart identifier + + 1. The first part is the SVH (strict version hash) of the crate they + were originally defined in + + 2. The second part is the ast::NodeId of the definition in their + original crate + + 3. The final part is a concatenation of the type IDs of their concrete + type arguments if they are generic types. + +3. Tuple-, pointer-, and function types are structurally identified, which + means that they are equivalent if their component types are equivalent + (i.e., `(i32, i32)` is the same regardless in which crate it is used). + +This algorithm also provides a stable ID for types that are defined in one +crate but instantiated from metadata within another crate. We just have to +take care to always map crate and `NodeId`s back to the original crate +context. + +As a side-effect these unique type IDs also help to solve a problem arising +from lifetime parameters. Since lifetime parameters are completely omitted +in debuginfo, more than one `Ty` instance may map to the same debuginfo +type metadata, that is, some struct `Struct<'a>` may have N instantiations +with different concrete substitutions for `'a`, and thus there will be N +`Ty` instances for the type `Struct<'a>` even though it is not generic +otherwise. Unfortunately this means that we cannot use `ty::type_id()` as +cheap identifier for type metadata -- we have done this in the past, but it +led to unnecessary metadata duplication in the best case and LLVM +assertions in the worst. However, the unique type ID as described above +*can* be used as identifier. Since it is comparatively expensive to +construct, though, `ty::type_id()` is still used additionally as an +optimization for cases where the exact same type has been seen before +(which is most of the time). diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -//! # Debug Info Module -//! -//! This module serves the purpose of generating debug symbols. We use LLVM's -//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) -//! features for generating the debug information. The general principle is -//! this: -//! -//! Given the right metadata in the LLVM IR, the LLVM code generator is able to -//! create DWARF debug symbols for the given code. The -//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured -//! much like DWARF *debugging information entries* (DIE), representing type -//! information such as datatype layout, function signatures, block layout, -//! variable location and scope information, etc. It is the purpose of this -//! module to generate correct metadata and insert it into the LLVM IR. -//! -//! As the exact format of metadata trees may change between different LLVM -//! versions, we now use LLVM -//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) -//! to create metadata where possible. This will hopefully ease the adaption of -//! this module to future LLVM versions. -//! -//! The public API of the module is a set of functions that will insert the -//! correct metadata into the LLVM IR when called with the right parameters. -//! The module is thus driven from an outside client with functions like -//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. -//! -//! Internally the module will try to reuse already created metadata by -//! utilizing a cache. The way to get a shared metadata node when needed is -//! thus to just call the corresponding function in this module: -//! -//! let file_metadata = file_metadata(cx, file); -//! -//! The function will take care of probing the cache for an existing node for -//! that exact file path. -//! -//! All private state used by the module is stored within either the -//! CrateDebugContext struct (owned by the CodegenCx) or the -//! FunctionDebugContext (owned by the FunctionCx). -//! -//! This file consists of three conceptual sections: -//! 1. The public interface of the module -//! 2. Module-internal metadata creation functions -//! 3. Minor utility functions -//! -//! -//! ## Recursive Types -//! -//! Some kinds of types, such as structs and enums can be recursive. That means -//! that the type definition of some type X refers to some other type which in -//! turn (transitively) refers to X. This introduces cycles into the type -//! referral graph. A naive algorithm doing an on-demand, depth-first traversal -//! of this graph when describing types, can get trapped in an endless loop -//! when it reaches such a cycle. -//! -//! For example, the following simple type for a singly-linked list... -//! -//! ``` -//! struct List { -//! value: i32, -//! tail: Option>, -//! } -//! ``` -//! -//! will generate the following callstack with a naive DFS algorithm: -//! -//! ``` -//! describe(t = List) -//! describe(t = i32) -//! describe(t = Option>) -//! describe(t = Box) -//! describe(t = List) // at the beginning again... -//! ... -//! ``` -//! -//! To break cycles like these, we use "forward declarations". That is, when -//! the algorithm encounters a possibly recursive type (any struct or enum), it -//! immediately creates a type description node and inserts it into the cache -//! *before* describing the members of the type. This type description is just -//! a stub (as type members are not described and added to it yet) but it -//! allows the algorithm to already refer to the type. After the stub is -//! inserted into the cache, the algorithm continues as before. If it now -//! encounters a recursive reference, it will hit the cache and does not try to -//! describe the type anew. -//! -//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum, -//! which represents a kind of continuation, storing all state needed to -//! continue traversal at the type members after the type has been registered -//! with the cache. (This implementation approach might be a tad over- -//! engineered and may change in the future) -//! -//! -//! ## Source Locations and Line Information -//! -//! In addition to data type descriptions the debugging information must also -//! allow to map machine code locations back to source code locations in order -//! to be useful. This functionality is also handled in this module. The -//! following functions allow to control source mappings: -//! -//! + set_source_location() -//! + clear_source_location() -//! + start_emitting_source_locations() -//! -//! `set_source_location()` allows to set the current source location. All IR -//! instructions created after a call to this function will be linked to the -//! given source location, until another location is specified with -//! `set_source_location()` or the source location is cleared with -//! `clear_source_location()`. In the later case, subsequent IR instruction -//! will not be linked to any source location. As you can see, this is a -//! stateful API (mimicking the one in LLVM), so be careful with source -//! locations set by previous calls. It's probably best to not rely on any -//! specific state being present at a given point in code. -//! -//! One topic that deserves some extra attention is *function prologues*. At -//! the beginning of a function's machine code there are typically a few -//! instructions for loading argument values into allocas and checking if -//! there's enough stack space for the function to execute. This *prologue* is -//! not visible in the source code and LLVM puts a special PROLOGUE END marker -//! into the line table at the first non-prologue instruction of the function. -//! In order to find out where the prologue ends, LLVM looks for the first -//! instruction in the function body that is linked to a source location. So, -//! when generating prologue instructions we have to make sure that we don't -//! emit source location information until the 'real' function body begins. For -//! this reason, source location emission is disabled by default for any new -//! function being codegened and is only activated after a call to the third -//! function from the list above, `start_emitting_source_locations()`. This -//! function should be called right before regularly starting to codegen the -//! top-level block of the given function. -//! -//! There is one exception to the above rule: `llvm.dbg.declare` instruction -//! must be linked to the source location of the variable being declared. For -//! function parameters these `llvm.dbg.declare` instructions typically occur -//! in the middle of the prologue, however, they are ignored by LLVM's prologue -//! detection. The `create_argument_metadata()` and related functions take care -//! of linking the `llvm.dbg.declare` instructions to the correct source -//! locations even while source location emission is still disabled, so there -//! is no need to do anything special with source location handling here. -//! -//! ## Unique Type Identification -//! -//! In order for link-time optimization to work properly, LLVM needs a unique -//! type identifier that tells it across compilation units which types are the -//! same as others. This type identifier is created by -//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm: -//! -//! (1) Primitive types have their name as ID -//! (2) Structs, enums and traits have a multipart identifier -//! -//! (1) The first part is the SVH (strict version hash) of the crate they -//! were originally defined in -//! -//! (2) The second part is the ast::NodeId of the definition in their -//! original crate -//! -//! (3) The final part is a concatenation of the type IDs of their concrete -//! type arguments if they are generic types. -//! -//! (3) Tuple-, pointer and function types are structurally identified, which -//! means that they are equivalent if their component types are equivalent -//! (i.e., (i32, i32) is the same regardless in which crate it is used). -//! -//! This algorithm also provides a stable ID for types that are defined in one -//! crate but instantiated from metadata within another crate. We just have to -//! take care to always map crate and `NodeId`s back to the original crate -//! context. -//! -//! As a side-effect these unique type IDs also help to solve a problem arising -//! from lifetime parameters. Since lifetime parameters are completely omitted -//! in debuginfo, more than one `Ty` instance may map to the same debuginfo -//! type metadata, that is, some struct `Struct<'a>` may have N instantiations -//! with different concrete substitutions for `'a`, and thus there will be N -//! `Ty` instances for the type `Struct<'a>` even though it is not generic -//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as -//! cheap identifier for type metadata -- we have done this in the past, but it -//! led to unnecessary metadata duplication in the best case and LLVM -//! assertions in the worst. However, the unique type ID as described above -//! *can* be used as identifier. Since it is comparatively expensive to -//! construct, though, `ty::type_id()` is still used additionally as an -//! optimization for cases where the exact same type has been seen before -//! (which is most of the time). diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1083,9 +1083,9 @@ ); } - // Insert `llvm.ident` metadata on the wasm32 targets since that will + // Insert `llvm.ident` metadata on the wasm targets since that will // get hooked up to the "producer" sections `processed-by` information. - if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if tcx.sess.target.is_like_wasm { let name_metadata = llvm::LLVMMDStringInContext( debug_context.llcontext, rustc_producer.as_ptr().cast(), @@ -1962,9 +1962,7 @@ let discriminant_type_metadata = |discr: Primitive| { let enumerators_metadata: Vec<_> = match enum_type.kind() { - ty::Adt(def, _) => def - .discriminants(tcx) - .zip(&def.variants) + ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); let is_unsigned = match discr.ty.kind() { @@ -2336,9 +2334,7 @@ if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); let names = get_parameter_names(cx, generics); - let template_params: Vec<_> = substs - .iter() - .zip(names) + let template_params: Vec<_> = iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,4 @@ -// See doc.rs for documentation. -mod doc; +#![doc = include_str!("doc.md")] use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; @@ -38,6 +37,7 @@ use libc::c_uint; use smallvec::SmallVec; use std::cell::RefCell; +use std::iter; use tracing::debug; mod create_scope_map; @@ -344,7 +344,7 @@ spflags |= DISPFlags::SPFlagOptimized; } if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) { - if id.to_def_id() == def_id { + if id == def_id { spflags |= DISPFlags::SPFlagMainSubprogram; } } @@ -449,9 +449,7 @@ // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); - substs - .iter() - .zip(names) + iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/intrinsic.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1053,46 +1053,48 @@ let vec_ty = bx.type_vector(elem_ty, in_len); let (intr_name, fn_ty) = match name { - sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), - sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), + sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), _ => return_error!("unrecognized intrinsic `{}`", name), }; - let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(&llvm_name, llvm::UnnamedAddr::No, fn_ty); let c = bx.call(f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); - unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) }; Ok(c) } if std::matches!( name, - sym::simd_fsqrt - | sym::simd_fsin - | sym::simd_fcos + sym::simd_ceil | sym::simd_fabs - | sym::simd_floor - | sym::simd_ceil - | sym::simd_fexp + | sym::simd_fcos | sym::simd_fexp2 + | sym::simd_fexp | sym::simd_flog10 | sym::simd_flog2 | sym::simd_flog - | sym::simd_fpowi - | sym::simd_fpow + | sym::simd_floor | sym::simd_fma + | sym::simd_fpow + | sym::simd_fpowi + | sym::simd_fsin + | sym::simd_fsqrt + | sym::simd_round + | sym::simd_trunc ) { return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -8,10 +8,12 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] +#![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] use back::write::{create_informational_target_machine, create_target_machine}; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm/ffi.rs 2021-06-17 03:53:50.000000000 +0000 @@ -190,33 +190,6 @@ RealPredicateTrue = 15, } -impl RealPredicate { - pub fn from_generic(realpred: rustc_codegen_ssa::common::RealPredicate) -> Self { - match realpred { - rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => { - RealPredicate::RealPredicateFalse - } - rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ, - rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT, - rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE, - rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT, - rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE, - rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE, - rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD, - rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO, - rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ, - rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT, - rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE, - rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT, - rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE, - rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE, - rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => { - RealPredicate::RealPredicateTrue - } - } - } -} - /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] @@ -711,7 +684,7 @@ } impl CounterMappingRegion { - pub fn code_region( + crate fn code_region( counter: coverage_map::Counter, file_id: u32, start_line: u32, @@ -731,7 +704,10 @@ } } - pub fn expansion_region( + // 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, start_line: u32, @@ -751,7 +727,10 @@ } } - pub fn skipped_region( + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn skipped_region( file_id: u32, start_line: u32, start_col: u32, @@ -770,7 +749,10 @@ } } - pub fn gap_region( + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn gap_region( counter: coverage_map::Counter, file_id: u32, start_line: u32, @@ -1031,6 +1013,7 @@ pub fn LLVMSetSection(Global: &Value, Section: *const c_char); pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); + pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); pub fn LLVMGetAlignment(Global: &Value) -> c_uint; pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); @@ -1371,7 +1354,7 @@ 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 LLVMRustSetHasUnsafeAlgebra(Instr: &Value); + pub fn LLVMRustSetFastMath(Instr: &Value); // Memory pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; @@ -2145,7 +2128,13 @@ pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); - pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine); + pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; + pub fn LLVMRustGetTargetFeature( + T: &TargetMachine, + Index: size_t, + Feature: &mut *const c_char, + Desc: &mut *const c_char, + ); pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; pub fn LLVMRustCreateTargetMachine( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/llvm_util.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,5 @@ use crate::back::write::create_informational_target_machine; -use crate::llvm; +use crate::{llvm, llvm_util}; use libc::c_int; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; @@ -10,6 +10,7 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy}; use std::ffi::{CStr, CString}; +use std::ptr; use std::slice; use std::str; use std::sync::atomic::{AtomicBool, Ordering}; @@ -83,6 +84,17 @@ if !sess.opts.debugging_opts.no_generate_arange_section { add("-generate-arange-section", false); } + + // FIXME(nagisa): disable the machine outliner by default in LLVM versions 11, where it was + // introduced and up. + // + // This should remain in place until https://reviews.llvm.org/D103167 is fixed. If LLVM + // has been upgraded since, consider adjusting the version check below to contain an upper + // bound. + if llvm_util::get_version() >= (11, 0, 0) { + add("-enable-machine-outliner=never", false); + } + match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { @@ -98,6 +110,9 @@ // during inlining. Unfortunately these may block other optimizations. add("-preserve-alignment-assumptions-during-inlining=false", false); + // Use non-zero `import-instr-limit` multiplier for cold callsites. + add("-import-cold-multiplier=0.1", false); + for arg in sess_args { add(&(*arg), true); } @@ -189,15 +204,77 @@ } } +fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { + let len = unsafe { llvm::LLVMRustGetTargetFeaturesCount(tm) }; + let mut ret = Vec::with_capacity(len); + for i in 0..len { + unsafe { + let mut feature = ptr::null(); + let mut desc = ptr::null(); + llvm::LLVMRustGetTargetFeature(tm, i, &mut feature, &mut desc); + if feature.is_null() || desc.is_null() { + bug!("LLVM returned a `null` target feature string"); + } + let feature = CStr::from_ptr(feature).to_str().unwrap_or_else(|e| { + bug!("LLVM returned a non-utf8 feature string: {}", e); + }); + let desc = CStr::from_ptr(desc).to_str().unwrap_or_else(|e| { + bug!("LLVM returned a non-utf8 feature string: {}", e); + }); + ret.push((feature, desc)); + } + } + ret +} + +fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) { + let mut target_features = llvm_target_features(tm); + let mut rustc_target_features = supported_target_features(sess) + .iter() + .filter_map(|(feature, _gate)| { + let llvm_feature = to_llvm_feature(sess, *feature); + // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. + target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| { + let (_f, desc) = target_features.remove(index); + (*feature, desc) + }) + }) + .collect::>(); + rustc_target_features.extend_from_slice(&[( + "crt-static", + "Enables C Run-time Libraries to be statically linked", + )]); + let max_feature_len = target_features + .iter() + .chain(rustc_target_features.iter()) + .map(|(feature, _desc)| feature.len()) + .max() + .unwrap_or(0); + + println!("Features supported by rustc for this target:"); + for (feature, desc) in &rustc_target_features { + println!(" {1:0$} - {2}.", max_feature_len, feature, desc); + } + println!("\nCode-generation features supported by LLVM for this target:"); + for (feature, desc) in &target_features { + println!(" {1:0$} - {2}.", max_feature_len, feature, desc); + } + if target_features.len() == 0 { + println!(" Target features listing is not supported by this LLVM version."); + } + println!("\nUse +feature to enable a feature, or -feature to disable it."); + println!("For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n"); + println!("Code-generation features cannot be used in cfg or #[target_feature],"); + println!("and may be renamed or removed in a future version of LLVM or rustc.\n"); +} + pub(crate) fn print(req: PrintRequest, sess: &Session) { require_inited(); let tm = create_informational_target_machine(sess); - unsafe { - match req { - PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm), - PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm), - _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), - } + match req { + PrintRequest::TargetCPUs => unsafe { llvm::LLVMRustPrintTargetCPUs(tm) }, + PrintRequest::TargetFeatures => print_target_features(sess, tm), + _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/mono_item.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/mono_item.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_llvm/src/mono_item.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_llvm/src/mono_item.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,7 +10,9 @@ use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::FnAbiExt; use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_session::config::CrateType; use rustc_target::abi::LayoutOf; +use rustc_target::spec::RelocModel; use tracing::debug; impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -35,6 +37,9 @@ unsafe { llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); + if self.should_assume_dso_local(linkage, visibility) { + llvm::LLVMRustSetDSOLocal(g, true); + } } self.instances.borrow_mut().insert(instance, g); @@ -79,6 +84,42 @@ attributes::from_fn_attrs(self, lldecl, instance); + unsafe { + if self.should_assume_dso_local(linkage, visibility) { + llvm::LLVMRustSetDSOLocal(lldecl, true); + } + } + self.instances.borrow_mut().insert(instance, lldecl); } } + +impl CodegenCx<'ll, 'tcx> { + /// Whether a definition (NB: not 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( + &self, + linkage: Linkage, + visibility: Visibility, + ) -> bool { + if matches!(linkage, Linkage::Internal | Linkage::Private) { + return true; + } + + if visibility != Visibility::Default && linkage != Linkage::ExternalWeak { + return true; + } + + // Static relocation model should force copy relocations everywhere. + if self.tcx.sess.relocation_model() == RelocModel::Static { + return true; + } + + // Symbols from executables can't really be imported any further. + if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) { + return true; + } + + return false; + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -11,11 +11,10 @@ bitflags = "1.2.1" cc = "1.0.1" itertools = "0.9" -memmap2 = "0.2.1" tracing = "0.1" libc = "0.2.50" -jobserver = "0.1.11" -tempfile = "3.1" +jobserver = "0.1.22" +tempfile = "3.2" pathdiff = "0.2.0" rustc_serialize = { path = "../rustc_serialize" } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/linker.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/linker.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/linker.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/linker.rs 2021-06-17 03:53:50.000000000 +0000 @@ -130,6 +130,8 @@ fn group_end(&mut self); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} + fn add_no_exec(&mut self) {} + fn add_as_needed(&mut self) {} fn finalize(&mut self); } @@ -184,7 +186,7 @@ // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.is_like_osx && self.sess.target.arch != "wasm32" + !self.sess.target.is_like_osx && !self.sess.target.is_like_wasm } // Some platforms take hints about whether a library is static or dynamic. @@ -641,6 +643,20 @@ fn add_eh_frame_header(&mut self) { self.linker_arg("--eh-frame-hdr"); } + + fn add_no_exec(&mut self) { + if self.sess.target.is_like_windows { + self.linker_arg("--nxcompat"); + } else if self.sess.target.linker_is_gnu { + self.linker_arg("-znoexecstack"); + } + } + + fn add_as_needed(&mut self) { + if self.sess.target.linker_is_gnu { + self.linker_arg("--as-needed"); + } + } } pub struct MsvcLinker<'a> { @@ -878,6 +894,10 @@ fn linker_plugin_lto(&mut self) { // Do nothing } + + fn add_no_exec(&mut self) { + self.cmd.arg("/NXCOMPAT"); + } } pub struct EmLinker<'a> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/link.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/link.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/link.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/link.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_middle::middle::cstore::{EncodedMetadata, LibSource}; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo}; -use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet}; +use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; @@ -16,7 +16,7 @@ use rustc_span::symbol::Symbol; use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; -use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target}; +use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; use super::archive::ArchiveBuilder; use super::command::Command; @@ -922,28 +922,20 @@ .map(|channel| format!("-{}", channel)) .unwrap_or_default(); - match sess.opts.target_triple.triple() { - "aarch64-apple-darwin" | "x86_64-apple-darwin" => { - // On Apple platforms, the sanitizer is always built as a dylib, and - // LLVM will link to `@rpath/*.dylib`, so we need to specify an - // rpath to the library as well (the rpath should be absolute, see - // PR #41352 for details). - let filename = format!("rustc{}_rt.{}", channel, name); - let path = find_sanitizer_runtime(&sess, &filename); - let rpath = path.to_str().expect("non-utf8 component in path"); - linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); - linker.link_dylib(Symbol::intern(&filename)); - } - "aarch64-fuchsia" - | "aarch64-unknown-linux-gnu" - | "x86_64-fuchsia" - | "x86_64-unknown-freebsd" - | "x86_64-unknown-linux-gnu" => { - let filename = format!("librustc{}_rt.{}.a", channel, name); - let path = find_sanitizer_runtime(&sess, &filename).join(&filename); - linker.link_whole_rlib(&path); - } - _ => {} + if sess.target.is_like_osx { + // On Apple platforms, the sanitizer is always built as a dylib, and + // LLVM will link to `@rpath/*.dylib`, so we need to specify an + // rpath to the library as well (the rpath should be absolute, see + // PR #41352 for details). + let filename = format!("rustc{}_rt.{}", channel, name); + let path = find_sanitizer_runtime(&sess, &filename); + let rpath = path.to_str().expect("non-utf8 component in path"); + linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); + linker.link_dylib(Symbol::intern(&filename)); + } else { + let filename = format!("librustc{}_rt.{}.a", channel, name); + let path = find_sanitizer_runtime(&sess, &filename).join(&filename); + linker.link_whole_rlib(&path); } } @@ -1419,15 +1411,10 @@ } } -/// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes. +/// Add arbitrary "user defined" args defined from command line. /// FIXME: Determine where exactly these args need to be inserted. -fn add_user_defined_link_args( - cmd: &mut dyn Linker, - sess: &Session, - codegen_results: &CodegenResults, -) { +fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) { cmd.args(&sess.opts.cg.link_args); - cmd.args(&*codegen_results.crate_info.link_args); } /// Add arbitrary "late link" args defined by the target spec. @@ -1651,6 +1638,16 @@ cmd.add_eh_frame_header(); } + // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER + // Make the binary compatible with data execution prevention schemes. + cmd.add_no_exec(); + + // NO-OPT-OUT, OBJECT-FILES-NO + // Avoid linking to dynamic libraries unless they satisfy some undefined symbols + // at the point at which they are specified on the command line. + // Must be passed before any dynamic libraries. + cmd.add_as_needed(); + // NO-OPT-OUT, OBJECT-FILES-NO if crt_objects_fallback { cmd.no_crt_objects(); @@ -1746,7 +1743,7 @@ ); // OBJECT-FILES-NO, AUDIT-ORDER - if sess.opts.cg.profile_generate.enabled() || sess.opts.debugging_opts.instrument_coverage { + if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() { cmd.pgo_gen(); } @@ -1759,7 +1756,7 @@ add_rpath_args(cmd, sess, codegen_results, out_filename); // OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT - add_user_defined_link_args(cmd, sess, codegen_results); + add_user_defined_link_args(cmd, sess); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER cmd.finalize(); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/lto.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/lto.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/lto.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/lto.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,6 +2,7 @@ use crate::traits::*; use crate::ModuleCodegen; +use rustc_data_structures::memmap::Mmap; use rustc_errors::FatalError; use std::ffi::CString; @@ -93,7 +94,7 @@ pub enum SerializedModule { Local(M), FromRlib(Vec), - FromUncompressedFile(memmap2::Mmap), + FromUncompressedFile(Mmap), } impl SerializedModule { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/symbol_export.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,7 +15,8 @@ use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{SymbolName, TyCtxt}; -use rustc_session::config::{CrateType, SanitizerSet}; +use rustc_session::config::CrateType; +use rustc_target::spec::SanitizerSet; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(&tcx.sess.crate_types()) @@ -188,9 +189,7 @@ } } - if tcx.sess.opts.debugging_opts.instrument_coverage - || tcx.sess.opts.cg.profile_generate.enabled() - { + if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { // These are weak symbols that point to the profile version and the // profile name, which need to be treated as exported so LTO doesn't nix // them. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/write.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/write.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/write.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/back/write.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,6 +10,7 @@ use crate::traits::*; use jobserver::{Acquired, Client}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; @@ -27,12 +28,12 @@ use rustc_middle::ty::TyCtxt; use rustc_session::cgu_reuse_tracker::CguReuseTracker; use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType}; -use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath}; +use rustc_session::config::{Passes, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; -use rustc_target::spec::{MergeFunctions, PanicStrategy}; +use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet}; use std::any::Any; use std::fs; @@ -106,7 +107,7 @@ pub vectorize_loop: bool, pub vectorize_slp: bool, pub merge_functions: bool, - pub inline_threshold: Option, + pub inline_threshold: Option, pub new_llvm_pass_manager: bool, pub emit_lifetime_markers: bool, } @@ -176,7 +177,7 @@ // The rustc option `-Zinstrument_coverage` injects intrinsic calls to // `llvm.instrprof.increment()`, which requires the LLVM `instrprof` pass. - if sess.opts.debugging_opts.instrument_coverage { + if sess.instrument_coverage() { passes.push("instrprof".to_owned()); } passes @@ -1093,7 +1094,7 @@ // only place where we have access to the compiler `Session`. // - LLVM work can be done on any thread. // - Codegen can only happen on the main thread. - // - Each thread doing substantial work most be in possession of a `Token` + // - Each thread doing substantial work must be in possession of a `Token` // from the `Jobserver`. // - The compiler process always holds one `Token`. Any additional `Tokens` // have to be requested from the `Jobserver`. @@ -1145,7 +1146,7 @@ // if possible. These two goals are at odds with each other: If memory // consumption were not an issue, we could just let the main thread produce // LLVM WorkItems at full speed, assuring maximal utilization of - // Tokens/LLVM worker threads. However, since codegen usual is faster + // Tokens/LLVM worker threads. However, since codegen is usually faster // than LLVM processing, the queue of LLVM WorkItems would fill up and each // WorkItem potentially holds on to a substantial amount of memory. // @@ -1958,7 +1959,7 @@ .unwrap_or_else(|e| panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e)); let mmap = unsafe { - memmap2::Mmap::map(&file).unwrap_or_else(|e| { + Mmap::map(file).unwrap_or_else(|e| { panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e) }) }; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/base.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{par_iter, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -348,12 +348,29 @@ cx: &'a Bx::CodegenCx, ) -> Option { let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?; - let instance = Instance::mono(cx.tcx(), main_def_id.to_def_id()); + let main_is_local = main_def_id.is_local(); + let instance = Instance::mono(cx.tcx(), main_def_id); - if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) { + if main_is_local { // We want to create the wrapper in the same codegen unit as Rust's main // function. - return None; + if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) { + return None; + } + } else { + // FIXME: Add support for non-local main fn codegen + let span = cx.tcx().main_def.unwrap().span; + let n = 28937; + cx.sess() + .struct_span_err(span, "entry symbol `main` from foreign crate is not yet supported.") + .note(&format!( + "see issue #{} \ + for more information", + n, n, + )) + .emit(); + cx.sess().abort_if_errors(); + bug!(); } let main_llfn = cx.get_fn_addr(instance); @@ -366,7 +383,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, rust_main: Bx::Value, - rust_main_def_id: LocalDefId, + rust_main_def_id: DefId, use_start_lang_item: bool, ) -> Bx::Function { // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, @@ -754,7 +771,6 @@ is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), - link_args: tcx.link_args(LOCAL_CRATE), crate_name: Default::default(), used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs 2021-06-17 03:53:50.000000000 +0000 @@ -24,21 +24,39 @@ pub struct Counter { // Important: The layout (order and types of fields) must match its C++ counterpart. pub kind: CounterKind, - pub id: u32, + id: u32, } impl Counter { + /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the + /// `id` is not used. pub fn zero() -> Self { Self { kind: CounterKind::Zero, id: 0 } } + /// Constructs a new `Counter` of kind `CounterValueReference`, and converts + /// the given 1-based counter_id to the required 0-based equivalent for + /// the `Counter` encoding. pub fn counter_value_reference(counter_id: CounterValueReference) -> Self { - Self { kind: CounterKind::CounterValueReference, id: counter_id.into() } + Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() } } + /// Constructs a new `Counter` of kind `Expression`. pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } } + + /// Returns true if the `Counter` kind is `Zero`. + pub fn is_zero(&self) -> bool { + matches!(self.kind, CounterKind::Zero) + } + + /// An explicitly-named function to get the ID value, making it more obvious + /// that the stored value is now 0-based. + pub fn zero_based_id(&self) -> u32 { + debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); + self.id + } } /// 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) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs 2021-06-17 03:53:50.000000000 +0000 @@ -31,27 +31,44 @@ pub struct FunctionCoverage<'tcx> { instance: Instance<'tcx>, source_hash: u64, + is_used: bool, counters: IndexVec>, expressions: IndexVec>, unreachable_regions: Vec, } impl<'tcx> FunctionCoverage<'tcx> { + /// Creates a new set of coverage data for a used (called) function. pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, true) + } + + /// Creates a new set of coverage data for an unused (never called) function. + pub fn unused(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, false) + } + + fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { let coverageinfo = tcx.coverageinfo(instance.def_id()); debug!( - "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}", - instance, coverageinfo + "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}. is_used={}", + instance, coverageinfo, is_used ); Self { instance, source_hash: 0, // will be set with the first `add_counter()` + is_used, counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), unreachable_regions: Vec::new(), } } + /// Returns true for a used (called) function, and false for an unused function. + pub fn is_used(&self) -> bool { + self.is_used + } + /// Sets the function source hash value. If called multiple times for the same function, all /// calls should have the same hash value. pub fn set_function_source_hash(&mut self, source_hash: u64) { @@ -128,8 +145,8 @@ &'a self, ) -> (Vec, impl Iterator) { assert!( - self.source_hash != 0, - "No counters provided the source_hash for function: {:?}", + self.source_hash != 0 || !self.is_used, + "No counters provided the source_hash for used function: {:?}", self.instance ); @@ -146,9 +163,7 @@ 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. - entry.as_ref().map(|region| { - (Counter::counter_value_reference(index as CounterValueReference), region) - }) + entry.as_ref().map(|region| (Counter::counter_value_reference(index), region)) }) } @@ -189,9 +204,15 @@ if id == ExpressionOperandId::ZERO { Some(Counter::zero()) } else if id.index() < self.counters.len() { + debug_assert!( + id.index() > 0, + "ExpressionOperandId indexes for counters are 1-based, but this id={}", + id.index() + ); // Note: Some codegen-injected Counters may be only referenced by `Expression`s, // and may not have their own `CodeRegion`s, let index = CounterValueReference::from(id.index()); + // Note, the conversion to LLVM `Counter` adjusts the index to be zero-based. Some(Counter::counter_value_reference(index)) } else { let index = self.expression_index(u32::from(id)); @@ -216,19 +237,60 @@ let optional_region = &expression.region; let Expression { lhs, op, rhs, .. } = *expression; - if let Some(Some((lhs_counter, rhs_counter))) = - id_to_counter(&new_indexes, lhs).map(|lhs_counter| { + if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs) + .map(|lhs_counter| { id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter)) }) { + if lhs_counter.is_zero() && op.is_subtract() { + // The left side of a subtraction was probably optimized out. As an example, + // a branch condition might be evaluated as a constant expression, and the + // branch could be removed, dropping unused counters in the process. + // + // Since counters are unsigned, we must assume the result of the expression + // can be no more and no less than zero. An expression known to evaluate to zero + // does not need to be added to the coverage map. + // + // Coverage test `loops_branches.rs` includes multiple variations of branches + // based on constant conditional (literal `true` or `false`), and demonstrates + // that the expected counts are still correct. + debug!( + "Expression subtracts from zero (assume unreachable): \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, lhs, op, rhs, optional_region, + ); + rhs_counter = Counter::zero(); + } debug_assert!( - (lhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + lhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((lhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "lhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + lhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + debug_assert!( - (rhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + rhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((rhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "rhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + rhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + // Both operands exist. `Expression` operands exist in `self.expressions` and have // been assigned a `new_index`. let mapped_expression_index = @@ -251,11 +313,15 @@ expression_regions.push((Counter::expression(mapped_expression_index), region)); } } else { - debug!( - "Ignoring expression with one or more missing operands: \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, lhs, op, rhs, optional_region, - ) + bug!( + "expression has one or more missing operands \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, + lhs, + op, + rhs, + optional_region, + ); } } (counter_expressions, expression_regions.into_iter()) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,8 +5,9 @@ #![feature(try_blocks)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(associated_type_bounds)] +#![feature(iter_zip)] #![recursion_limit = "256"] #![feature(box_syntax)] @@ -137,7 +138,6 @@ pub native_libraries: FxHashMap>, pub crate_name: FxHashMap, pub used_libraries: Vec, - pub link_args: Lrc>, pub used_crate_source: FxHashMap>, pub used_crates_static: Vec<(CrateNum, LibSource)>, pub used_crates_dynamic: Vec<(CrateNum, LibSource)>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/block.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/block.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/block.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/block.rs 2021-06-17 03:53:50.000000000 +0000 @@ -822,41 +822,37 @@ InlineAsmOperandRef::InOut { reg, late, in_value, out_place } } mir::InlineAsmOperand::Const { ref value } => { - if let mir::Operand::Constant(constant) = value { - let const_value = self - .eval_mir_constant(constant) - .unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved")); - let ty = constant.ty(); - let size = bx.layout_of(ty).size; - let scalar = match const_value { - ConstValue::Scalar(s) => s, - _ => span_bug!( - span, - "expected Scalar for promoted asm const, but got {:#?}", - const_value - ), - }; - let value = scalar.assert_bits(size); - let string = match ty.kind() { - ty::Uint(_) => value.to_string(), - ty::Int(int_ty) => { - match int_ty.normalize(bx.tcx().sess.target.pointer_width) { - ty::IntTy::I8 => (value as i8).to_string(), - ty::IntTy::I16 => (value as i16).to_string(), - ty::IntTy::I32 => (value as i32).to_string(), - ty::IntTy::I64 => (value as i64).to_string(), - ty::IntTy::I128 => (value as i128).to_string(), - ty::IntTy::Isize => unreachable!(), - } + let const_value = self + .eval_mir_constant(value) + .unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved")); + let ty = value.ty(); + let size = bx.layout_of(ty).size; + let scalar = match const_value { + ConstValue::Scalar(s) => s, + _ => span_bug!( + span, + "expected Scalar for promoted asm const, but got {:#?}", + const_value + ), + }; + let value = scalar.assert_bits(size); + let string = match ty.kind() { + ty::Uint(_) => value.to_string(), + ty::Int(int_ty) => { + match int_ty.normalize(bx.tcx().sess.target.pointer_width) { + ty::IntTy::I8 => (value as i8).to_string(), + ty::IntTy::I16 => (value as i16).to_string(), + ty::IntTy::I32 => (value as i32).to_string(), + ty::IntTy::I64 => (value as i64).to_string(), + ty::IntTy::I128 => (value as i128).to_string(), + ty::IntTy::Isize => unreachable!(), } - ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), - ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), - _ => span_bug!(span, "asm const has bad type {}", ty), - }; - InlineAsmOperandRef::Const { string } - } else { - span_bug!(span, "asm const is not a constant"); - } + } + ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), + ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), + _ => span_bug!(span, "asm const has bad type {}", ty), + }; + InlineAsmOperandRef::Const { string } } mir::InlineAsmOperand::SymFn { ref value } => { let literal = self.monomorphize(value.literal); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/constant.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/constant.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/constant.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/constant.rs 2021-06-17 03:53:50.000000000 +0000 @@ -30,10 +30,10 @@ mir::ConstantKind::Val(val, _) => return Ok(val), }; match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => self + ty::ConstKind::Unevaluated(ct) => self .cx .tcx() - .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) + .const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None) .map_err(|err| { self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs 2021-06-17 03:53:50.000000000 +0000 @@ -33,10 +33,10 @@ let coverageinfo = bx.tcx().coverageinfo(instance.def_id()); - let fn_name = bx.create_pgo_func_name_var(instance); + let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(u32::from(id)); + let index = bx.const_u32(id.zero_based_index()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", fn_name, hash, num_counters, index, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; -use rustc_target::abi::{LayoutOf, Size}; +use rustc_target::abi::Size; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -265,33 +265,25 @@ None => continue, }; - let mut layout = base.layout; let mut direct_offset = Size::ZERO; // FIXME(eddyb) use smallvec here. let mut indirect_offsets = vec![]; + let mut place = base; for elem in &var.projection[..] { match *elem { mir::ProjectionElem::Deref => { indirect_offsets.push(Size::ZERO); - layout = bx.cx().layout_of( - layout - .ty - .builtin_deref(true) - .unwrap_or_else(|| { - span_bug!(var.source_info.span, "cannot deref `{}`", layout.ty) - }) - .ty, - ); + place = place.project_deref(bx); } mir::ProjectionElem::Field(field, _) => { let i = field.index(); let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset); - *offset += layout.fields.offset(i); - layout = layout.field(bx.cx(), i); + *offset += place.layout.fields.offset(i); + place = place.project_field(bx, i); } mir::ProjectionElem::Downcast(_, variant) => { - layout = layout.for_variant(bx.cx(), variant); + place = place.project_downcast(bx, variant); } _ => span_bug!( var.source_info.span, @@ -301,7 +293,39 @@ } } - bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets); + // When targeting MSVC, create extra allocas for arguments instead of pointing multiple + // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records + // not DWARF and LLVM doesn't support translating the resulting + // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView. + // Creating extra allocas on the stack makes the resulting debug info simple enough + // that LLVM can generate correct CodeView records and thus the values appear in the + // debugger. (#83709) + let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc + && self.mir.local_kind(local) == mir::LocalKind::Arg + // LLVM can handle simple things but anything more complex than just a direct + // offset or one indirect offset of 0 is too complex for it to generate CV records + // correctly. + && (direct_offset != Size::ZERO + || !matches!(&indirect_offsets[..], [Size::ZERO] | [])); + + if should_create_individual_allocas { + // Create a variable which will be a pointer to the actual value + let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut { + mutbl: mir::Mutability::Mut, + ty: place.layout.ty, + })); + let ptr_layout = bx.layout_of(ptr_ty); + let alloca = PlaceRef::alloca(bx, ptr_layout); + bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill")); + + // Write the pointer to the variable + bx.store(place.llval, alloca.llval, alloca.align); + + // Point the debug info to `*alloca` for the current variable + bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO]); + } else { + bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets); + } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -282,9 +282,7 @@ IndexVec>, IndexVec>, ) { - block_bxs - .iter_enumerated() - .zip(cleanup_kinds) + iter::zip(block_bxs.iter_enumerated(), cleanup_kinds) .map(|((bb, &llbb), cleanup_kind)| { match *cleanup_kind { CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/place.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/place.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/place.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/place.rs 2021-06-17 03:53:50.000000000 +0000 @@ -402,6 +402,18 @@ downcast } + pub fn project_deref>(&self, bx: &mut Bx) -> Self { + let target_ty = self.layout.ty.builtin_deref(true).expect("failed to deref"); + let layout = bx.layout_of(target_ty.ty); + + PlaceRef { + llval: bx.load(self.llval, self.align), + llextra: None, + layout, + align: layout.align.abi, + } + } + pub fn storage_live>(&self, bx: &mut Bx) { bx.lifetime_start(self.llval, self.layout.size); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/mir/rvalue.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,7 +11,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::sym; @@ -385,10 +385,10 @@ bx.inttoptr(usize_llval, ll_t_out) } (CastTy::Float, CastTy::Int(IntTy::I)) => { - cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out) } (CastTy::Float, CastTy::Int(_)) => { - cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out) } _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty), }; @@ -790,7 +790,6 @@ x: Bx::Value, float_ty: Bx::Type, int_ty: Bx::Type, - int_layout: TyAndLayout<'tcx>, ) -> Bx::Value { if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; @@ -891,134 +890,39 @@ let int_min = bx.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128); let zero = bx.cx().const_uint(int_ty, 0); - // The codegen here differs quite a bit depending on whether our builder's - // `fptosi` and `fptoui` instructions may trap for out-of-bounds values. If - // they don't trap then we can start doing everything inline with a - // `select` instruction because it's ok to execute `fptosi` and `fptoui` - // even if we don't use the results. - if !bx.fptosui_may_trap(x, int_ty) { - // Step 1 ... - let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); - let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); - - // Step 2: We use two comparisons and two selects, with %s1 being the - // result: - // %less_or_nan = fcmp ult %x, %f_min - // %greater = fcmp olt %x, %f_max - // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result - // %s1 = select %greater, int_ty::MAX, %s0 - // Note that %less_or_nan uses an *unordered* comparison. This - // comparison is true if the operands are not comparable (i.e., if x is - // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if - // x is NaN. - // - // Performance note: Unordered comparison can be lowered to a "flipped" - // comparison and a negation, and the negation can be merged into the - // select. Therefore, it not necessarily any more expensive than a - // ordered ("normal") comparison. Whether these optimizations will be - // performed is ultimately up to the backend, but at least x86 does - // perform them. - let s0 = bx.select(less_or_nan, int_min, fptosui_result); - let s1 = bx.select(greater, int_max, s0); - - // Step 3: NaN replacement. - // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. - // Therefore we only need to execute this step for signed integer types. - if signed { - // LLVM has no isNaN predicate, so we use (x == x) instead - let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); - bx.select(cmp, s1, zero) - } else { - s1 - } + // Step 1 ... + let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); + let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); + + // Step 2: We use two comparisons and two selects, with %s1 being the + // result: + // %less_or_nan = fcmp ult %x, %f_min + // %greater = fcmp olt %x, %f_max + // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result + // %s1 = select %greater, int_ty::MAX, %s0 + // Note that %less_or_nan uses an *unordered* comparison. This + // comparison is true if the operands are not comparable (i.e., if x is + // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if + // x is NaN. + // + // Performance note: Unordered comparison can be lowered to a "flipped" + // comparison and a negation, and the negation can be merged into the + // select. Therefore, it not necessarily any more expensive than a + // ordered ("normal") comparison. Whether these optimizations will be + // performed is ultimately up to the backend, but at least x86 does + // perform them. + let s0 = bx.select(less_or_nan, int_min, fptosui_result); + let s1 = bx.select(greater, int_max, s0); + + // Step 3: NaN replacement. + // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. + // Therefore we only need to execute this step for signed integer types. + if signed { + // LLVM has no isNaN predicate, so we use (x == x) instead + let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); + bx.select(cmp, s1, zero) } else { - // In this case we cannot execute `fptosi` or `fptoui` and then later - // discard the result. The builder is telling us that these instructions - // will trap on out-of-bounds values, so we need to use basic blocks and - // control flow to avoid executing the `fptosi` and `fptoui` - // instructions. - // - // The general idea of what we're constructing here is, for f64 -> i32: - // - // ;; block so far... %0 is the argument - // %result = alloca i32, align 4 - // %inbound_lower = fcmp oge double %0, 0xC1E0000000000000 - // %inbound_upper = fcmp ole double %0, 0x41DFFFFFFFC00000 - // ;; match (inbound_lower, inbound_upper) { - // ;; (true, true) => %0 can be converted without trapping - // ;; (false, false) => %0 is a NaN - // ;; (true, false) => %0 is too large - // ;; (false, true) => %0 is too small - // ;; } - // ;; - // ;; The (true, true) check, go to %convert if so. - // %inbounds = and i1 %inbound_lower, %inbound_upper - // br i1 %inbounds, label %convert, label %specialcase - // - // convert: - // %cvt = call i32 @llvm.wasm.trunc.signed.i32.f64(double %0) - // store i32 %cvt, i32* %result, align 4 - // br label %done - // - // specialcase: - // ;; Handle the cases where the number is NaN, too large or too small - // - // ;; Either (true, false) or (false, true) - // %is_not_nan = or i1 %inbound_lower, %inbound_upper - // ;; Figure out which saturated value we are interested in if not `NaN` - // %saturated = select i1 %inbound_lower, i32 2147483647, i32 -2147483648 - // ;; Figure out between saturated and NaN representations - // %result_nan = select i1 %is_not_nan, i32 %saturated, i32 0 - // store i32 %result_nan, i32* %result, align 4 - // br label %done - // - // done: - // %r = load i32, i32* %result, align 4 - // ;; ... - let done = bx.build_sibling_block("float_cast_done"); - let mut convert = bx.build_sibling_block("float_cast_convert"); - let mut specialcase = bx.build_sibling_block("float_cast_specialcase"); - - let result = PlaceRef::alloca(bx, int_layout); - result.storage_live(bx); - - // Use control flow to figure out whether we can execute `fptosi` in a - // basic block, or whether we go to a different basic block to implement - // the saturating logic. - let inbound_lower = bx.fcmp(RealPredicate::RealOGE, x, f_min); - let inbound_upper = bx.fcmp(RealPredicate::RealOLE, x, f_max); - let inbounds = bx.and(inbound_lower, inbound_upper); - bx.cond_br(inbounds, convert.llbb(), specialcase.llbb()); - - // Translation of the `convert` basic block - let cvt = if signed { convert.fptosi(x, int_ty) } else { convert.fptoui(x, int_ty) }; - convert.store(cvt, result.llval, result.align); - convert.br(done.llbb()); - - // Translation of the `specialcase` basic block. Note that like above - // we try to be a bit clever here for unsigned conversions. In those - // cases the `int_min` is zero so we don't need two select instructions, - // just one to choose whether we need `int_max` or not. If - // `inbound_lower` is true then we're guaranteed to not be `NaN` and - // since we're greater than zero we must be saturating to `int_max`. If - // `inbound_lower` is false then we're either NaN or less than zero, so - // we saturate to zero. - let result_nan = if signed { - let is_not_nan = specialcase.or(inbound_lower, inbound_upper); - let saturated = specialcase.select(inbound_lower, int_max, int_min); - specialcase.select(is_not_nan, saturated, zero) - } else { - specialcase.select(inbound_lower, int_max, int_min) - }; - specialcase.store(result_nan, result.llval, result.align); - specialcase.br(done.llbb()); - - // Translation of the `done` basic block, positioning ourselves to - // continue from that point as well. - *bx = done; - let ret = bx.load(result.llval, result.align); - result.storage_dead(bx); - ret + s1 } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/target_features.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/target_features.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/target_features.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/target_features.rs 2021-06-17 03:53:50.000000000 +0000 @@ -26,6 +26,7 @@ ("vfp2", Some(sym::arm_target_feature)), ("vfp3", Some(sym::arm_target_feature)), ("vfp4", Some(sym::arm_target_feature)), + ("fp-armv8", Some(sym::arm_target_feature)), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -160,7 +161,7 @@ "mips" | "mips64" => MIPS_ALLOWED_FEATURES, "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" => WASM_ALLOWED_FEATURES, + "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, _ => &[], } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/builder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -171,7 +171,6 @@ fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; - fn fptosui_may_trap(&self, val: Self::Value, dest_ty: Self::Type) -> bool; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,14 +1,26 @@ use super::BackendTypes; +use rustc_hir::def_id::DefId; use rustc_middle::mir::coverage::*; use rustc_middle::ty::Instance; -pub trait CoverageInfoMethods: BackendTypes { +pub trait CoverageInfoMethods<'tcx>: BackendTypes { fn coverageinfo_finalize(&self); + + /// Codegen a small function that will never be called, with one counter + /// that will never be incremented, that gives LLVM coverage tools a + /// function definition it needs in order to resolve coverage map references + /// to unused functions. This is necessary so unused functions will appear + /// as uncovered (coverage execution count `0`) in LLVM coverage reports. + fn define_unused_fn(&self, def_id: DefId); + + /// For LLVM codegen, returns a function-specific `Value` for a global + /// string, to hold the function name passed to LLVM intrinsic + /// `instrprof.increment()`. The `Value` is only created once per instance. + /// Multiple invocations with the same instance return the same `Value`. + fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; } pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { - fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; - /// Returns true if the function source hash was added to the coverage map (even if it had /// already been added, for this instance). Returns false *only* if `-Z instrument-coverage` is /// not enabled (a coverage map is not being generated). diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_codegen_ssa/src/traits/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -58,7 +58,7 @@ + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> @@ -74,7 +74,7 @@ + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -8,7 +8,7 @@ doctest = false [dependencies] -arrayvec = { version = "0.5.1", default-features = false } +arrayvec = { version = "0.7", default-features = false } ena = "0.14" indexmap = "1.5.1" tracing = "0.1" @@ -17,7 +17,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_graphviz = { path = "../rustc_graphviz" } cfg-if = "0.1.2" -crossbeam-utils = { version = "0.7", features = ["nightly"] } +crossbeam-utils = { version = "0.8", features = ["nightly"] } stable_deref_trait = "1.0.0" rayon = { version = "0.3.1", package = "rustc-rayon" } rayon-core = { version = "0.3.1", package = "rustc-rayon-core" } @@ -28,11 +28,13 @@ measureme = "9.1.0" libc = "0.2" stacker = "0.1.12" -tempfile = "3.0.5" +tempfile = "3.2" [dependencies.parking_lot] version = "0.11" -features = ["nightly"] [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["fileapi", "psapi"] } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +memmap2 = "0.2.1" diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/fingerprint.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/fingerprint.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/fingerprint.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/fingerprint.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,10 +1,7 @@ use crate::stable_hasher; -use rustc_serialize::{ - opaque::{self, EncodeResult, FileEncodeResult}, - Decodable, Encodable, -}; +use rustc_serialize::{Decodable, Encodable}; +use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::mem::{self, MaybeUninit}; #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)] #[repr(C)] @@ -64,14 +61,27 @@ format!("{:x}{:x}", self.0, self.1) } - pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result { - let mut bytes: [MaybeUninit; 16] = MaybeUninit::uninit_array(); + #[inline] + pub fn to_le_bytes(&self) -> [u8; 16] { + // This seems to optimize to the same machine code as + // `unsafe { mem::transmute(*k) }`. Well done, LLVM! :) + let mut result = [0u8; 16]; + + let first_half: &mut [u8; 8] = (&mut result[0..8]).try_into().unwrap(); + *first_half = self.0.to_le_bytes(); - decoder.read_raw_bytes(&mut bytes)?; + let second_half: &mut [u8; 8] = (&mut result[8..16]).try_into().unwrap(); + *second_half = self.1.to_le_bytes(); - let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) }; + result + } - Ok(Fingerprint(u64::from_le(l), u64::from_le(r))) + #[inline] + pub fn from_le_bytes(bytes: [u8; 16]) -> Fingerprint { + Fingerprint( + u64::from_le_bytes(bytes[0..8].try_into().unwrap()), + u64::from_le_bytes(bytes[8..16].try_into().unwrap()), + ) } } @@ -130,55 +140,19 @@ impl_stable_hash_via_hash!(Fingerprint); impl Encodable for Fingerprint { + #[inline] fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.encode_fingerprint(self) + s.emit_raw_bytes(&self.to_le_bytes()[..])?; + Ok(()) } } impl Decodable for Fingerprint { + #[inline] fn decode(d: &mut D) -> Result { - d.decode_fingerprint() - } -} - -pub trait FingerprintEncoder: rustc_serialize::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>; -} - -pub trait FingerprintDecoder: rustc_serialize::Decoder { - fn decode_fingerprint(&mut self) -> Result; -} - -impl FingerprintEncoder for E { - default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> { - panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::()); - } -} - -impl FingerprintEncoder for opaque::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes); - Ok(()) - } -} - -impl FingerprintEncoder for opaque::FileEncoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes) - } -} - -impl FingerprintDecoder for D { - default fn decode_fingerprint(&mut self) -> Result { - panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::()); - } -} - -impl FingerprintDecoder for opaque::Decoder<'_> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(self) + let mut bytes = [0u8; 16]; + d.read_raw_bytes_into(&mut bytes[..])?; + Ok(Fingerprint::from_le_bytes(bytes)) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -13,7 +13,6 @@ #![feature(unboxed_closures)] #![feature(generator_trait)] #![feature(fn_traits)] -#![feature(int_bits_const)] #![feature(min_specialization)] #![feature(auto_traits)] #![feature(nll)] @@ -85,6 +84,7 @@ pub mod stable_map; pub mod svh; pub use ena::snapshot_vec; +pub mod memmap; pub mod sorted_map; pub mod stable_set; #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/memmap.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/memmap.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/memmap.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/memmap.rs 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,47 @@ +use std::fs::File; +use std::io; +use std::ops::Deref; + +use crate::owning_ref::StableAddress; + +/// A trivial wrapper for [`memmap2::Mmap`] that implements [`StableAddress`]. +#[cfg(not(target_arch = "wasm32"))] +pub struct Mmap(memmap2::Mmap); + +#[cfg(target_arch = "wasm32")] +pub struct Mmap(Vec); + +#[cfg(not(target_arch = "wasm32"))] +impl Mmap { + #[inline] + pub unsafe fn map(file: File) -> io::Result { + memmap2::Mmap::map(&file).map(Mmap) + } +} + +#[cfg(target_arch = "wasm32")] +impl Mmap { + #[inline] + pub unsafe fn map(mut file: File) -> io::Result { + use std::io::Read; + + let mut data = Vec::new(); + file.read_to_end(&mut data)?; + Ok(Mmap(data)) + } +} + +impl Deref for Mmap { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &*self.0 + } +} + +// SAFETY: On architectures other than WASM, mmap is used as backing storage. The address of this +// memory map is stable. On WASM, `Vec` is used as backing storage. The `Mmap` type doesn't +// export any function that can cause the `Vec` to be re-allocated. As such the address of the +// bytes inside this `Vec` is stable. +unsafe impl StableAddress for Mmap {} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/sso/map.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/sso/map.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/sso/map.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/sso/map.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,11 +18,8 @@ // for reasonably small arrays that stay // small in vast majority of cases. // -// '8' is choosen as a sane default, to be +// '8' is chosen as a sane default, to be // reevaluated later. -// -// Note: As of now ArrayVec design prevents -// us from making it user-customizable. const SSO_ARRAY_SIZE: usize = 8; /// Small-storage-optimized implementation of a map. @@ -70,7 +67,7 @@ #[derive(Clone)] pub enum SsoHashMap { - Array(ArrayVec<[(K, V); SSO_ARRAY_SIZE]>), + Array(ArrayVec<(K, V), SSO_ARRAY_SIZE>), Map(FxHashMap), } @@ -411,7 +408,7 @@ impl IntoIterator for SsoHashMap { type IntoIter = EitherIter< - as IntoIterator>::IntoIter, + as IntoIterator>::IntoIter, as IntoIterator>::IntoIter, >; type Item = ::Item; @@ -441,7 +438,7 @@ impl<'a, K, V> IntoIterator for &'a SsoHashMap { type IntoIter = EitherIter< std::iter::Map< - <&'a ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, + <&'a ArrayVec<(K, V), 8> as IntoIterator>::IntoIter, fn(&'a (K, V)) -> (&'a K, &'a V), >, <&'a FxHashMap as IntoIterator>::IntoIter, @@ -459,7 +456,7 @@ impl<'a, K, V> IntoIterator for &'a mut SsoHashMap { type IntoIter = EitherIter< std::iter::Map< - <&'a mut ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, + <&'a mut ArrayVec<(K, V), 8> as IntoIterator>::IntoIter, fn(&'a mut (K, V)) -> (&'a K, &'a mut V), >, <&'a mut FxHashMap as IntoIterator>::IntoIter, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/svh.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/svh.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/svh.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/svh.rs 2021-06-17 03:53:50.000000000 +0000 @@ -19,7 +19,7 @@ impl Svh { /// Creates a new `Svh` given the hash. If you actually want to /// compute the SVH from some HIR, you want the `calculate_svh` - /// function found in `librustc_incremental`. + /// function found in `rustc_incremental`. pub fn new(hash: u64) -> Svh { Svh { hash } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/tagged_ptr/drop.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/tagged_ptr/drop.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/tagged_ptr/drop.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/tagged_ptr/drop.rs 2021-06-17 03:53:50.000000000 +0000 @@ -42,18 +42,9 @@ pub fn pointer_ref(&self) -> &P::Target { self.raw.pointer_ref() } - pub fn pointer_mut(&mut self) -> &mut P::Target - where - P: std::ops::DerefMut, - { - self.raw.pointer_mut() - } pub fn tag(&self) -> T { self.raw.tag() } - pub fn set_tag(&mut self, tag: T) { - self.raw.set_tag(tag); - } } impl std::ops::Deref for TaggedPtr diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec/tests.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,42 @@ +use super::*; + +impl ThinVec { + fn into_vec(self) -> Vec { + self.into() + } +} + +#[test] +fn test_from_iterator() { + assert_eq!(std::iter::empty().collect::>().into_vec(), Vec::::new()); + assert_eq!(std::iter::once(42).collect::>().into_vec(), vec![42]); + assert_eq!(vec![1, 2].into_iter().collect::>().into_vec(), vec![1, 2]); + assert_eq!(vec![1, 2, 3].into_iter().collect::>().into_vec(), vec![1, 2, 3]); +} + +#[test] +fn test_into_iterator_owned() { + assert_eq!(ThinVec::new().into_iter().collect::>(), Vec::::new()); + assert_eq!(ThinVec::from(vec![1]).into_iter().collect::>(), vec![1]); + assert_eq!(ThinVec::from(vec![1, 2]).into_iter().collect::>(), vec![1, 2]); + assert_eq!(ThinVec::from(vec![1, 2, 3]).into_iter().collect::>(), vec![1, 2, 3]); +} + +#[test] +fn test_into_iterator_ref() { + assert_eq!(ThinVec::new().iter().collect::>(), Vec::<&String>::new()); + assert_eq!(ThinVec::from(vec![1]).iter().collect::>(), vec![&1]); + assert_eq!(ThinVec::from(vec![1, 2]).iter().collect::>(), vec![&1, &2]); + assert_eq!(ThinVec::from(vec![1, 2, 3]).iter().collect::>(), vec![&1, &2, &3]); +} + +#[test] +fn test_into_iterator_ref_mut() { + assert_eq!(ThinVec::new().iter_mut().collect::>(), Vec::<&mut String>::new()); + assert_eq!(ThinVec::from(vec![1]).iter_mut().collect::>(), vec![&mut 1]); + assert_eq!(ThinVec::from(vec![1, 2]).iter_mut().collect::>(), vec![&mut 1, &mut 2]); + assert_eq!( + ThinVec::from(vec![1, 2, 3]).iter_mut().collect::>(), + vec![&mut 1, &mut 2, &mut 3], + ); +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/thin_vec.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,7 @@ use crate::stable_hasher::{HashStable, StableHasher}; +use std::iter::FromIterator; + /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. @@ -10,6 +12,14 @@ pub fn new() -> Self { ThinVec(None) } + + pub fn iter(&self) -> std::slice::Iter<'_, T> { + self.into_iter() + } + + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { + self.into_iter() + } } impl From> for ThinVec { @@ -46,6 +56,42 @@ } } +impl FromIterator for ThinVec { + fn from_iter>(iter: I) -> Self { + // `Vec::from_iter()` should not allocate if the iterator is empty. + let vec: Vec<_> = iter.into_iter().collect(); + if vec.is_empty() { ThinVec(None) } else { ThinVec(Some(Box::new(vec))) } + } +} + +impl IntoIterator for ThinVec { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + // This is still performant because `Vec::new()` does not allocate. + self.0.map_or_else(Vec::new, |ptr| *ptr).into_iter() + } +} + +impl<'a, T> IntoIterator for &'a ThinVec { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.as_ref().iter() + } +} + +impl<'a, T> IntoIterator for &'a mut ThinVec { + type Item = &'a mut T; + type IntoIter = std::slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.as_mut().iter_mut() + } +} + impl Extend for ThinVec { fn extend>(&mut self, iter: I) { match *self { @@ -80,3 +126,6 @@ Self(None) } } + +#[cfg(test)] +mod tests; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/work_queue.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/work_queue.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_data_structures/src/work_queue.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_data_structures/src/work_queue.rs 2021-06-17 03:53:50.000000000 +0000 @@ -41,10 +41,4 @@ None } } - - /// Returns `true` if nothing is enqueued. - #[inline] - pub fn is_empty(&self) -> bool { - self.deque.is_empty() - } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_driver/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_driver/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_driver/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_driver/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -146,6 +146,7 @@ pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self { Self { at_args, callbacks, file_loader: None, emitter: None, make_codegen_backend: None } } + /// Used by cg_clif. pub fn set_make_codegen_backend( &mut self, make_codegen_backend: Option< @@ -155,10 +156,12 @@ self.make_codegen_backend = make_codegen_backend; self } + /// Used by RLS. pub fn set_emitter(&mut self, emitter: Option>) -> &mut Self { self.emitter = emitter; self } + /// Used by RLS. pub fn set_file_loader( &mut self, file_loader: Option>, @@ -792,7 +795,7 @@ println!("host: {}", config::host_triple()); println!("release: {}", unw(util::release_str())); if cfg!(feature = "llvm") { - get_builtin_codegen_backend("llvm")().print_version(); + get_builtin_codegen_backend(&None, "llvm")().print_version(); } } } @@ -842,7 +845,8 @@ ); } -fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { +/// Write to stdout lint command options, together with a list of all available lints +pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { println!( " Available lint options: @@ -895,7 +899,12 @@ let print_lints = |lints: Vec<&Lint>| { for lint in lints { let name = lint.name_lower().replace("_", "-"); - println!(" {} {:7.7} {}", padded(&name), lint.default_level.as_str(), lint.desc); + println!( + " {} {:7.7} {}", + padded(&name), + lint.default_level(sess.edition()).as_str(), + lint.desc + ); } println!("\n"); }; @@ -1081,7 +1090,7 @@ if cg_flags.iter().any(|x| *x == "passes=list") { if cfg!(feature = "llvm") { - get_builtin_codegen_backend("llvm")().print_passes(); + get_builtin_codegen_backend(&None, "llvm")().print_passes(); } return None; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_driver/src/pretty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_driver/src/pretty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_driver/src/pretty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_driver/src/pretty.rs 2021-06-17 03:53:50.000000000 +0000 @@ -108,13 +108,6 @@ /// (Rust does not yet support upcasting from a trait object to /// an object for one of its super-traits.) fn pp_ann(&self) -> &dyn pprust_hir::PpAnn; - - /// Computes an user-readable representation of a path, if possible. - fn node_path(&self, id: hir::HirId) -> Option { - self.hir_map().and_then(|map| map.def_path_from_hir_id(id)).map(|path| { - path.data.into_iter().map(|elem| elem.data.to_string()).collect::>().join("::") - }) - } } struct NoAnn<'hir> { @@ -327,10 +320,6 @@ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { self } - - fn node_path(&self, id: hir::HirId) -> Option { - Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id())) - } } impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { @@ -471,21 +460,6 @@ format!("{:#?}", krate) }), - ThirTree => { - let mut out = String::new(); - abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); - debug!("pretty printing THIR tree"); - for did in tcx.body_owners() { - let hir = tcx.hir(); - let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did))); - let arena = thir::Arena::default(); - let thir = - thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value); - let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir); - } - out - } - _ => unreachable!(), }; @@ -501,18 +475,40 @@ ppm: PpMode, ofile: Option<&Path>, ) -> Result<(), ErrorReported> { - let mut out = Vec::new(); - tcx.analysis(LOCAL_CRATE)?; - match ppm { - Mir => write_mir_pretty(tcx, None, &mut out).unwrap(), - MirCFG => write_mir_graphviz(tcx, None, &mut out).unwrap(), + let out = match ppm { + Mir => { + let mut out = Vec::new(); + write_mir_pretty(tcx, None, &mut out).unwrap(); + String::from_utf8(out).unwrap() + } + + MirCFG => { + let mut out = Vec::new(); + write_mir_graphviz(tcx, None, &mut out).unwrap(); + String::from_utf8(out).unwrap() + } + + ThirTree => { + let mut out = String::new(); + abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); + debug!("pretty printing THIR tree"); + for did in tcx.body_owners() { + let hir = tcx.hir(); + let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did))); + let arena = thir::Arena::default(); + let thir = + thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value); + let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir); + } + out + } + _ => unreachable!(), - } + }; - let out = std::str::from_utf8(&out).unwrap(); - write_or_print(out, ofile); + write_or_print(&out, ofile); Ok(()) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0128.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0128.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0128.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0128.md 2021-06-17 03:53:50.000000000 +0000 @@ -7,7 +7,7 @@ field1: T, field2: U, } -// error: type parameters with a default cannot use forward declared +// error: generic parameters with a default cannot use forward declared // identifiers ``` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0136.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0136.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0136.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0136.md 2021-06-17 03:53:50.000000000 +0000 @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + More than one `main` function was found. Erroneous code example: -```compile_fail,E0136 +```compile_fail fn main() { // ... } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0137.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0137.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0137.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0137.md 2021-06-17 03:53:50.000000000 +0000 @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + More than one function was declared with the `#[main]` attribute. Erroneous code example: -```compile_fail,E0137 +```compile_fail #![feature(main)] #[main] @@ -16,7 +18,7 @@ `#[main]` attribute. This is an error because there must be a unique entry point into a Rust program. Example: -``` +```compile_fail #![feature(main)] #[main] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0379.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0379.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0379.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0379.md 2021-06-17 03:53:50.000000000 +0000 @@ -3,8 +3,6 @@ Erroneous code example: ```compile_fail,E0379 -#![feature(const_fn)] - trait Foo { const fn bar() -> u32; // error! } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0404.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0404.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0404.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0404.md 2021-06-17 03:53:50.000000000 +0000 @@ -8,14 +8,15 @@ struct Bar; impl Foo for Bar {} // error: `Foo` is not a trait +fn baz(t: T) {} // error: `Foo` is not a trait ``` Another erroneous code example: ```compile_fail,E0404 -struct Foo; +type Foo = Iterator; -fn bar(t: T) {} // error: `Foo` is not a trait +fn bar(t: T) {} // error: `Foo` is a type alias ``` Please verify that the trait's name was not misspelled or that the right @@ -30,14 +31,27 @@ impl Foo for Bar { // ok! // functions implementation } + +fn baz(t: T) {} // ok! ``` -or: +Alternatively, you could introduce a new trait with your desired restrictions +as a super trait: ``` -trait Foo { - // some functions -} +# trait Foo {} +# struct Bar; +# impl Foo for Bar {} +trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo +fn baz(t: T) {} // also ok! +``` + +Finally, if you are on nightly and want to use a trait alias +instead of a type alias, you should use `#![feature(trait_alias)]`: + +``` +#![feature(trait_alias)] +trait Foo = Iterator; fn bar(t: T) {} // ok! ``` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0554.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0554.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0554.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0554.md 2021-06-17 03:53:50.000000000 +0000 @@ -4,8 +4,8 @@ Erroneous code example: ```ignore (depends on release channel) -#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the - // stable release channel +#![feature(lang_items)] // error: `#![feature]` may not be used on the + // stable release channel ``` If you need the feature, make sure to use a nightly release of the compiler diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0723.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0723.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0723.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0723.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -An unstable feature in `const` contexts was used. - -Erroneous code example: - -```compile_fail,E0723 -const fn foo(_: T) { // error! - // ... -} -``` - -To enable this feature on a nightly version of rustc, add the `const_fn` -feature flag: - -``` -#![feature(const_fn)] - -const fn foo(_: T) { // ok! - // ... -} -``` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0754.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0754.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0754.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0754.md 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,6 @@ Erroneous code examples: ```compile_fail,E0754 -# #![feature(non_ascii_idents)] mod řųśť; // error! @@ -17,8 +16,6 @@ attribute is specified. For example: ``` -# #![feature(non_ascii_idents)] - mod řųśť { // ok! const IS_GREAT: bool = true; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0764.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0764.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0764.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes/E0764.md 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,6 @@ Erroneous code example: ```compile_fail,E0764 -#![feature(const_fn)] #![feature(const_mut_refs)] fn main() { @@ -27,7 +26,6 @@ you can totally use it in constant functions: ``` -#![feature(const_fn)] #![feature(const_mut_refs)] const fn foo(x: usize) -> usize { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/error_codes.rs 2021-06-17 03:53:50.000000000 +0000 @@ -416,7 +416,6 @@ E0718: include_str!("./error_codes/E0718.md"), E0719: include_str!("./error_codes/E0719.md"), E0720: include_str!("./error_codes/E0720.md"), -E0723: include_str!("./error_codes/E0723.md"), E0724: include_str!("./error_codes/E0724.md"), E0725: include_str!("./error_codes/E0725.md"), E0727: include_str!("./error_codes/E0727.md"), @@ -636,6 +635,7 @@ E0717, // rustc_promotable without stability attribute // E0721, // `await` keyword E0722, // Malformed `#[optimize]` attribute +// E0723, unstable feature in `const` context E0726, // non-explicit (not `'_`) elided lifetime in unsupported position // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_error_codes/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_error_codes/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,4 @@ -#![cfg_attr(bootstrap, deny(invalid_codeblock_attributes))] -#![cfg_attr(not(bootstrap), deny(rustdoc::invalid_codeblock_attributes))] +#![deny(rustdoc::invalid_codeblock_attributes)] //! This library is used to gather all error codes into one place, //! the goal being to make their maintenance easier. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/diagnostic_builder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/diagnostic_builder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/diagnostic_builder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/diagnostic_builder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -157,19 +157,6 @@ buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } - /// Convenience function for internal use, clients should use one of the - /// span_* methods instead. - pub fn sub>( - &mut self, - level: Level, - message: &str, - span: Option, - ) -> &mut Self { - let span = span.map(|s| s.into()).unwrap_or_else(MultiSpan::new); - self.0.diagnostic.sub(level, message, span, None); - self - } - /// Delay emission of this diagnostic as a bug. /// /// This can be useful in contexts where an error indicates a bug but @@ -270,20 +257,6 @@ self } - /// See [`Diagnostic::multipart_suggestions()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability); - self - } - /// See [`Diagnostic::tool_only_multipart_suggestion()`]. pub fn tool_only_multipart_suggestion( &mut self, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/diagnostic.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/diagnostic.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/diagnostic.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/diagnostic.rs 2021-06-17 03:53:50.000000000 +0000 @@ -69,10 +69,6 @@ pub fn highlighted>(t: S) -> DiagnosticStyledString { DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) } - - pub fn content(&self) -> String { - self.0.iter().map(|x| x.content()).collect::() - } } #[derive(Debug, PartialEq, Eq)] @@ -81,14 +77,6 @@ Highlighted(String), } -impl StringPart { - pub fn content(&self) -> &str { - match self { - &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, - } - } -} - impl Diagnostic { pub fn new(level: Level, message: &str) -> Self { Diagnostic::new_with_code(level, None, message) @@ -156,7 +144,7 @@ self } - pub fn note_expected_found( + crate fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, expected: DiagnosticStyledString, @@ -166,7 +154,7 @@ self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } - pub fn note_unsuccessful_coercion( + crate fn note_unsuccessful_coercion( &mut self, expected: DiagnosticStyledString, found: DiagnosticStyledString, @@ -256,33 +244,33 @@ /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn span_note>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_note>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Note, msg, sp.into(), None); self } /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: &str) -> &mut Self { + crate fn warn(&mut self, msg: &str) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new(), None); self } /// Prints the span with a warning above it. /// This is like [`Diagnostic::warn()`], but it gets its own span. - pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Warning, msg, sp.into(), None); self } /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: &str) -> &mut Self { + crate fn help(&mut self, msg: &str) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), None); self } /// Prints the span with some help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. - pub fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Help, msg, sp.into(), None); self } @@ -311,36 +299,6 @@ self } - /// Show multiple suggestions that have multiple parts. - /// See also [`Diagnostic::multipart_suggestion()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - assert!(!suggestions.is_empty()); - for s in &suggestions { - assert!(!s.is_empty()); - } - self.suggestions.push(CodeSuggestion { - substitutions: suggestions - .into_iter() - .map(|suggestion| Substitution { - parts: suggestion - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }) - .collect(), - msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, - applicability, - tool_metadata: Default::default(), - }); - self - } - /// Prints out a message with for a multipart suggestion without showing the suggested code. /// /// This is intended to be used for suggestions that are obvious in what the changes need to @@ -567,7 +525,7 @@ self.code.clone() } - pub fn set_primary_message>(&mut self, msg: M) -> &mut Self { + crate fn set_primary_message>(&mut self, msg: M) -> &mut Self { self.message[0] = (msg.into(), Style::NoStyle); self } @@ -582,6 +540,8 @@ /// Convenience function for internal use, clients should use one of the /// public methods above. + /// + /// Used by `proc_macro_server` for implementing `server::Diagnostic`. pub fn sub( &mut self, level: Level, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/emitter.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/emitter.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/emitter.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/emitter.rs 2021-06-17 03:53:50.000000000 +0000 @@ -195,6 +195,9 @@ fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {} + /// Emit list of unused externs + fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {} + /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { true @@ -434,9 +437,15 @@ span: &mut MultiSpan, children: &mut Vec, ) { + let source_map = if let Some(ref sm) = source_map { + sm + } else { + return; + }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - for span in iter::once(&mut *span).chain(children.iter_mut().map(|child| &mut child.span)) { - self.fix_multispan_in_extern_macros(source_map, span); + self.fix_multispan_in_extern_macros(source_map, span); + for child in children.iter_mut() { + self.fix_multispan_in_extern_macros(source_map, &mut child.span); } debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } @@ -444,16 +453,7 @@ // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. // Since these locations are often difficult to read, // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros( - &self, - source_map: &Option>, - span: &mut MultiSpan, - ) { - let sm = match source_map { - Some(ref sm) => sm, - None => return, - }; - + fn fix_multispan_in_extern_macros(&self, source_map: &Lrc, span: &mut MultiSpan) { // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() @@ -461,7 +461,7 @@ .copied() .chain(span.span_labels().iter().map(|sp_label| sp_label.span)) .filter_map(|sp| { - if !sp.is_dummy() && sm.is_imported(sp) { + if !sp.is_dummy() && source_map.is_imported(sp) { let maybe_callsite = sp.source_callsite(); if sp != maybe_callsite { return Some((sp, maybe_callsite)); @@ -1232,7 +1232,6 @@ is_secondary: bool, ) -> io::Result<()> { let mut buffer = StyledBuffer::new(); - let header_style = if is_secondary { Style::HeaderMsg } else { Style::MainHeaderMsg }; if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message { @@ -1257,11 +1256,12 @@ buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); } + let header_style = if is_secondary { Style::HeaderMsg } else { Style::MainHeaderMsg }; if *level != Level::FailureNote { buffer.append(0, ": ", header_style); } for &(ref text, _) in msg.iter() { - buffer.append(0, text, header_style); + buffer.append(0, &replace_tabs(text), header_style); } } @@ -1470,9 +1470,7 @@ let mut to_add = FxHashMap::default(); for (depth, style) in depths { - if multilines.get(&depth).is_some() { - multilines.remove(&depth); - } else { + if multilines.remove(&depth).is_none() { to_add.insert(depth, style); } } @@ -1726,14 +1724,13 @@ if !self.short_message { draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); } - match emit_to_destination( + if let Err(e) = emit_to_destination( &buffer.render(), level, &mut self.dst, self.short_message, ) { - Ok(()) => (), - Err(e) => panic!("failed to emit error: {}", e), + panic!("failed to emit error: {}", e) } } if !self.short_message { @@ -2220,9 +2217,7 @@ }; let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; // All the chars that differ in capitalization are confusable (above): - let confusable = found - .chars() - .zip(suggested.chars()) + let confusable = iter::zip(found.chars(), suggested.chars()) .filter(|(f, s)| f != s) .all(|(f, s)| (ascii_confusables.contains(&f) || ascii_confusables.contains(&s))); confusable && found.to_lowercase() == suggested.to_lowercase() diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/json.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/json.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/json.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/json.rs 2021-06-17 03:53:50.000000000 +0000 @@ -159,6 +159,19 @@ } } + fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) { + let data = UnusedExterns { lint_level, unused_extern_names: unused_externs }; + let result = if self.pretty { + writeln!(&mut self.dst, "{}", as_pretty_json(&data)) + } else { + writeln!(&mut self.dst, "{}", as_json(&data)) + } + .and_then(|_| self.dst.flush()); + if let Err(e) = result { + panic!("failed to print unused externs: {:?}", e); + } + } + fn source_map(&self) -> Option<&Lrc> { Some(&self.sm) } @@ -322,6 +335,18 @@ future_incompat_report: Vec, } +// NOTE: Keep this in sync with the equivalent structs in rustdoc's +// doctest component (as well as cargo). +// We could unify this struct the one in rustdoc but they have different +// ownership semantics, so doing so would create wasteful allocations. +#[derive(Encodable)] +struct UnusedExterns<'a, 'b, 'c> { + /// The severity level of the unused dependencies lint + lint_level: &'a str, + /// List of unused externs by their names. + unused_extern_names: &'b [&'c str], +} + impl Diagnostic { fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let sugg = diag.suggestions.iter().map(|sugg| Diagnostic { @@ -493,7 +518,7 @@ h_end: usize, ) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: sf.get_line(index).map_or(String::new(), |l| l.into_owned()), + text: sf.get_line(index).map_or_else(String::new, |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,6 +6,7 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(extended_key_value_attributes)] +#![feature(iter_zip)] #![feature(nll)] #[macro_use] @@ -320,7 +321,7 @@ /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which - /// would be uneccessary repetition. + /// would be unnecessary repetition. taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain @@ -690,10 +691,6 @@ db } - pub fn failure(&self, msg: &str) { - self.inner.borrow_mut().failure(msg); - } - pub fn fatal(&self, msg: &str) -> FatalError { self.inner.borrow_mut().fatal(msg) } @@ -768,6 +765,10 @@ self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) } + pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) { + self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs) + } + pub fn delay_as_bug(&self, diagnostic: Diagnostic) { self.inner.borrow_mut().delay_as_bug(diagnostic) } @@ -842,6 +843,10 @@ self.emitter.emit_artifact_notification(path, artifact_type); } + fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) { + self.emitter.emit_unused_externs(lint_level, unused_externs); + } + fn treat_err_as_bug(&self) -> bool { self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get()) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/registry.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/registry.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/registry.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/registry.rs 2021-06-17 03:53:50.000000000 +0000 @@ -13,10 +13,6 @@ Registry { long_descriptions: long_descriptions.iter().copied().collect() } } - /// This will panic if an invalid error code is passed in - pub fn find_description(&self, code: &str) -> Option<&'static str> { - self.long_descriptions[code] - } /// Returns `InvalidErrorCode` if the code requested does not exist in the /// registry. Otherwise, returns an `Option` where `None` means the error /// code is valid but has no extended information. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/snippet.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/snippet.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/snippet.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/snippet.rs 2021-06-17 03:53:50.000000000 +0000 @@ -121,16 +121,6 @@ matches!(self.annotation_type, AnnotationType::MultilineLine(_)) } - pub fn is_multiline(&self) -> bool { - matches!( - self.annotation_type, - AnnotationType::Multiline(_) - | AnnotationType::MultilineStart(_) - | AnnotationType::MultilineLine(_) - | AnnotationType::MultilineEnd(_) - ) - } - pub fn len(&self) -> usize { // Account for usize underflows if self.end_col > self.start_col { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/styled_buffer.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/styled_buffer.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_errors/src/styled_buffer.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_errors/src/styled_buffer.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,35 +4,49 @@ #[derive(Debug)] pub struct StyledBuffer { - text: Vec>, - styles: Vec>, + lines: Vec>, +} + +#[derive(Debug, Clone)] +struct StyledChar { + chr: char, + style: Style, +} + +impl StyledChar { + const SPACE: Self = StyledChar::new(' ', Style::NoStyle); + + const fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } + } } impl StyledBuffer { pub fn new() -> StyledBuffer { - StyledBuffer { text: vec![], styles: vec![] } + StyledBuffer { lines: vec![] } } + /// Returns content of `StyledBuffer` splitted by lines and line styles pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(self.text.iter().all(|r| !r.contains(&'\t'))); + debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for (row, row_style) in self.text.iter().zip(&self.styles) { + for styled_line in &self.lines { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for (&c, &s) in row.iter().zip(row_style) { - if s != current_style { + for sc in styled_line { + if sc.style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); } - current_style = s; + current_style = sc.style; current_text = String::new(); } - current_text.push(c); + current_text.push(sc.chr); } if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); @@ -48,29 +62,25 @@ } fn ensure_lines(&mut self, line: usize) { - while line >= self.text.len() { - self.text.push(vec![]); - self.styles.push(vec![]); + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); } } + /// Sets `chr` with `style` for given `line`, `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); - if col < self.text[line].len() { - self.text[line][col] = chr; - self.styles[line][col] = style; - } else { - let mut i = self.text[line].len(); - while i < col { - self.text[line].push(' '); - self.styles[line].push(Style::NoStyle); - i += 1; - } - self.text[line].push(chr); - self.styles[line].push(style); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); } + self.lines[line][col] = StyledChar::new(chr, style); } + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { @@ -79,32 +89,40 @@ } } + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); - // Push the old content over to make room for new content - for _ in 0..string_len { - self.styles[line].insert(0, Style::NoStyle); - self.text[line].insert(0, ' '); + if !self.lines[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.lines[line].insert(0, StyledChar::SPACE); + } } self.puts(line, 0, string, style); } + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed pub fn append(&mut self, line: usize, string: &str, style: Style) { - if line >= self.text.len() { + if line >= self.lines.len() { self.puts(line, 0, string, style); } else { - let col = self.text[line].len(); + let col = self.lines[line].len(); self.puts(line, col, string, style); } } pub fn num_lines(&self) -> usize { - self.text.len() + self.lines.len() } + /// Set `style` for `line`, `col_start..col_end` range if: + /// 1. That line and column range exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style_range( &mut self, line: usize, @@ -118,10 +136,13 @@ } } + /// Set `style` for `line`, `col` if: + /// 1. That line and column exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { - if let Some(ref mut line) = self.styles.get_mut(line) { - if let Some(s) = line.get_mut(col) { - if *s == Style::NoStyle || *s == Style::Quotation || overwrite { + if let Some(ref mut line) = self.lines.get_mut(line) { + if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { + if overwrite || *s == Style::NoStyle || *s == Style::Quotation { *s = style; } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/base.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; -use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream}; +use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; @@ -46,26 +46,26 @@ Variant(ast::Variant), } -impl AstLike for Annotatable { - fn attrs(&self) -> &[Attribute] { +impl Annotatable { + pub fn span(&self) -> Span { match *self { - Annotatable::Item(ref item) => &item.attrs, - Annotatable::TraitItem(ref trait_item) => &trait_item.attrs, - Annotatable::ImplItem(ref impl_item) => &impl_item.attrs, - Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs, - Annotatable::Stmt(ref stmt) => stmt.attrs(), - Annotatable::Expr(ref expr) => &expr.attrs, - Annotatable::Arm(ref arm) => &arm.attrs, - Annotatable::ExprField(ref field) => &field.attrs, - Annotatable::PatField(ref fp) => &fp.attrs, - Annotatable::GenericParam(ref gp) => &gp.attrs, - Annotatable::Param(ref p) => &p.attrs, - Annotatable::FieldDef(ref sf) => &sf.attrs, - Annotatable::Variant(ref v) => &v.attrs(), + Annotatable::Item(ref item) => item.span, + Annotatable::TraitItem(ref trait_item) => trait_item.span, + Annotatable::ImplItem(ref impl_item) => impl_item.span, + Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, + Annotatable::Stmt(ref stmt) => stmt.span, + Annotatable::Expr(ref expr) => expr.span, + Annotatable::Arm(ref arm) => arm.span, + Annotatable::ExprField(ref field) => field.span, + Annotatable::PatField(ref fp) => fp.pat.span, + Annotatable::GenericParam(ref gp) => gp.ident.span, + Annotatable::Param(ref p) => p.span, + Annotatable::FieldDef(ref sf) => sf.span, + Annotatable::Variant(ref v) => v.span, } } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { match self { Annotatable::Item(item) => item.visit_attrs(f), Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f), @@ -83,44 +83,6 @@ } } - fn tokens_mut(&mut self) -> Option<&mut Option> { - match self { - Annotatable::Item(item) => item.tokens_mut(), - Annotatable::TraitItem(trait_item) => trait_item.tokens_mut(), - Annotatable::ImplItem(impl_item) => impl_item.tokens_mut(), - Annotatable::ForeignItem(foreign_item) => foreign_item.tokens_mut(), - Annotatable::Stmt(stmt) => stmt.tokens_mut(), - Annotatable::Expr(expr) => expr.tokens_mut(), - Annotatable::Arm(arm) => arm.tokens_mut(), - Annotatable::ExprField(field) => field.tokens_mut(), - Annotatable::PatField(fp) => fp.tokens_mut(), - Annotatable::GenericParam(gp) => gp.tokens_mut(), - Annotatable::Param(p) => p.tokens_mut(), - Annotatable::FieldDef(sf) => sf.tokens_mut(), - Annotatable::Variant(v) => v.tokens_mut(), - } - } -} - -impl Annotatable { - pub fn span(&self) -> Span { - match *self { - Annotatable::Item(ref item) => item.span, - Annotatable::TraitItem(ref trait_item) => trait_item.span, - Annotatable::ImplItem(ref impl_item) => impl_item.span, - Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, - Annotatable::Stmt(ref stmt) => stmt.span, - Annotatable::Expr(ref expr) => expr.span, - Annotatable::Arm(ref arm) => arm.span, - Annotatable::ExprField(ref field) => field.span, - Annotatable::PatField(ref fp) => fp.pat.span, - Annotatable::GenericParam(ref gp) => gp.ident.span, - Annotatable::Param(ref p) => p.span, - Annotatable::FieldDef(ref sf) => sf.span, - Annotatable::Variant(ref v) => v.span, - } - } - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { match self { Annotatable::Item(item) => visitor.visit_item(item), @@ -139,7 +101,7 @@ } } - crate fn into_nonterminal(self) -> Nonterminal { + pub fn into_nonterminal(self) -> Nonterminal { match self { Annotatable::Item(item) => token::NtItem(item), Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { @@ -161,10 +123,7 @@ } crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { - // Tokens of an attribute target may be invalidated by some outer `#[derive]` performing - // "full configuration" (attributes following derives on the same item should be the most - // common case), that's why synthesizing tokens is allowed. - nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::Yes) + nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No) } pub fn expect_item(self) -> P { @@ -868,6 +827,8 @@ /// Error type that denotes indeterminacy. pub struct Indeterminate; +pub type DeriveResolutions = Vec<(ast::Path, Option>)>; + pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; @@ -904,15 +865,12 @@ fn resolve_derives( &mut self, expn_id: ExpnId, - derives: Vec, force: bool, + derive_paths: &dyn Fn() -> DeriveResolutions, ) -> Result<(), Indeterminate>; /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId` /// back from resolver. - fn take_derive_resolutions( - &mut self, - expn_id: ExpnId, - ) -> Option, ast::Path)>>; + fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option; /// Path resolution logic for `#[cfg_accessible(path)]`. fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/build.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/build.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/build.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/build.rs 2021-06-17 03:53:50.000000000 +0000 @@ -253,17 +253,6 @@ let pathexpr = self.expr_path(self.path_global(sp, fn_path)); self.expr_call(sp, pathexpr, args) } - pub fn expr_method_call( - &self, - span: Span, - expr: P, - ident: Ident, - mut args: Vec>, - ) -> P { - args.insert(0, expr); - let segment = ast::PathSegment::from_ident(ident.with_span_pos(span)); - self.expr(span, ast::ExprKind::MethodCall(segment, args, span)) - } pub fn expr_block(&self, b: P) -> P { self.expr(b.span, ast::ExprKind::Block(b, None)) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/config.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/config.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/config.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/config.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,8 +2,10 @@ use rustc_ast::ptr::P; use rustc_ast::token::{DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree}; -use rustc_ast::{self as ast, AstLike, AttrItem, Attribute, MetaItem}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use rustc_ast::tokenstream::{DelimSpan, Spacing}; +use rustc_ast::tokenstream::{LazyTokenStream, TokenTree}; +use rustc_ast::{self as ast, AstLike, AttrItem, AttrStyle, Attribute, MetaItem}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::map_in_place::MapInPlace; @@ -23,7 +25,10 @@ pub struct StripUnconfigured<'a> { pub sess: &'a Session, pub features: Option<&'a Features>, - pub modified: bool, + /// If `true`, perform cfg-stripping on attached tokens. + /// This is only used for the input to derive macros, + /// which needs eager expansion of `cfg` and `cfg_attr` + pub config_tokens: bool, } fn get_features( @@ -194,7 +199,7 @@ // `cfg_attr`-process the crate's attributes and compute the crate's features. pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) { - let mut strip_unconfigured = StripUnconfigured { sess, features: None, modified: false }; + let mut strip_unconfigured = StripUnconfigured { sess, features: None, config_tokens: false }; let unconfigured_attrs = krate.attrs.clone(); let diag = &sess.parse_sess.span_diagnostic; @@ -241,24 +246,83 @@ pub fn configure(&mut self, mut node: T) -> Option { self.process_cfg_attrs(&mut node); if self.in_cfg(node.attrs()) { + self.try_configure_tokens(&mut node); Some(node) } else { - self.modified = true; None } } + fn try_configure_tokens(&mut self, node: &mut T) { + if self.config_tokens { + if let Some(Some(tokens)) = node.tokens_mut() { + let attr_annotated_tokens = tokens.create_token_stream(); + *tokens = LazyTokenStream::new(self.configure_tokens(&attr_annotated_tokens)); + } + } + } + fn configure_krate_attrs( &mut self, mut attrs: Vec, ) -> Option> { attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - if self.in_cfg(&attrs) { - Some(attrs) - } else { - self.modified = true; - None + if self.in_cfg(&attrs) { Some(attrs) } else { None } + } + + /// Performs cfg-expansion on `stream`, producing a new `AttrAnnotatedTokenStream`. + /// This is only used during the invocation of `derive` proc-macros, + /// which require that we cfg-expand their entire input. + /// Normal cfg-expansion operates on parsed AST nodes via the `configure` method + fn configure_tokens(&mut self, stream: &AttrAnnotatedTokenStream) -> AttrAnnotatedTokenStream { + fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool { + stream.0.iter().all(|(tree, _spacing)| match tree { + AttrAnnotatedTokenTree::Attributes(_) => false, + AttrAnnotatedTokenTree::Token(_) => true, + AttrAnnotatedTokenTree::Delimited(_, _, inner) => can_skip(inner), + }) + } + + if can_skip(stream) { + return stream.clone(); } + + let trees: Vec<_> = stream + .0 + .iter() + .flat_map(|(tree, spacing)| match tree.clone() { + AttrAnnotatedTokenTree::Attributes(mut data) => { + let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into(); + attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); + data.attrs = attrs.into(); + + if self.in_cfg(&data.attrs) { + data.tokens = LazyTokenStream::new( + self.configure_tokens(&data.tokens.create_token_stream()), + ); + Some((AttrAnnotatedTokenTree::Attributes(data), *spacing)).into_iter() + } else { + None.into_iter() + } + } + AttrAnnotatedTokenTree::Delimited(sp, delim, mut inner) => { + inner = self.configure_tokens(&inner); + Some((AttrAnnotatedTokenTree::Delimited(sp, delim, inner), *spacing)) + .into_iter() + } + AttrAnnotatedTokenTree::Token(token) => { + if let TokenKind::Interpolated(nt) = token.kind { + panic!( + "Nonterminal should have been flattened at {:?}: {:?}", + token.span, nt + ); + } else { + Some((AttrAnnotatedTokenTree::Token(token), *spacing)).into_iter() + } + } + }) + .collect(); + AttrAnnotatedTokenStream::new(trees) } /// Parse and expand all `cfg_attr` attributes into a list of attributes @@ -285,9 +349,6 @@ return vec![attr]; } - // A `#[cfg_attr]` either gets removed, or replaced with a new attribute - self.modified = true; - let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) { None => return vec![], Some(r) => r, @@ -311,7 +372,7 @@ expanded_attrs .into_iter() .flat_map(|(item, span)| { - let orig_tokens = attr.tokens(); + let orig_tokens = attr.tokens().to_tokenstream(); // We are taking an attribute of the form `#[cfg_attr(pred, attr)]` // and producing an attribute of the form `#[attr]`. We @@ -321,25 +382,34 @@ // Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token // for `attr` when we expand it to `#[attr]` - let pound_token = orig_tokens.trees().next().unwrap(); - if !matches!(pound_token, TokenTree::Token(Token { kind: TokenKind::Pound, .. })) { - panic!("Bad tokens for attribute {:?}", attr); + let mut orig_trees = orig_tokens.trees(); + let pound_token = match orig_trees.next().unwrap() { + TokenTree::Token(token @ Token { kind: TokenKind::Pound, .. }) => token, + _ => panic!("Bad tokens for attribute {:?}", attr), + }; + let pound_span = pound_token.span; + + let mut trees = vec![(AttrAnnotatedTokenTree::Token(pound_token), Spacing::Alone)]; + if attr.style == AttrStyle::Inner { + // For inner attributes, we do the same thing for the `!` in `#![some_attr]` + let bang_token = match orig_trees.next().unwrap() { + TokenTree::Token(token @ Token { kind: TokenKind::Not, .. }) => token, + _ => panic!("Bad tokens for attribute {:?}", attr), + }; + trees.push((AttrAnnotatedTokenTree::Token(bang_token), Spacing::Alone)); } // We don't really have a good span to use for the syntheized `[]` // in `#[attr]`, so just use the span of the `#` token. - let bracket_group = TokenTree::Delimited( - DelimSpan::from_single(pound_token.span()), + let bracket_group = AttrAnnotatedTokenTree::Delimited( + DelimSpan::from_single(pound_span), DelimToken::Bracket, item.tokens .as_ref() .unwrap_or_else(|| panic!("Missing tokens for {:?}", item)) .create_token_stream(), ); - let tokens = Some(LazyTokenStream::new(TokenStream::new(vec![ - (pound_token, Spacing::Alone), - (bracket_group, Spacing::Alone), - ]))); - + 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)) }) .collect() @@ -457,7 +527,8 @@ self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg); } - self.process_cfg_attrs(expr) + self.process_cfg_attrs(expr); + self.try_configure_tokens(&mut *expr); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/expand.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/expand.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/expand.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/expand.rs 2021-06-17 03:53:50.000000000 +0000 @@ -12,7 +12,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AstLike, AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs}; +use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; @@ -20,9 +20,9 @@ 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, PResult}; +use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; -use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, GateOr, Parser, RecoverComma}; +use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; @@ -206,30 +206,36 @@ } } +pub enum SupportsMacroExpansion { + No, + Yes { supports_inner_attrs: bool }, +} + impl AstFragmentKind { crate fn dummy(self, span: Span) -> AstFragment { self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment") } - /// Fragment supports macro expansion and not just inert attributes, `cfg` and `cfg_attr`. - pub fn supports_macro_expansion(self) -> bool { + pub fn supports_macro_expansion(self) -> SupportsMacroExpansion { match self { AstFragmentKind::OptExpr | AstFragmentKind::Expr - | AstFragmentKind::Pat - | AstFragmentKind::Ty | AstFragmentKind::Stmts - | AstFragmentKind::Items + | AstFragmentKind::Ty + | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false }, + AstFragmentKind::Items | AstFragmentKind::TraitItems | AstFragmentKind::ImplItems - | AstFragmentKind::ForeignItems => true, + | AstFragmentKind::ForeignItems => { + SupportsMacroExpansion::Yes { supports_inner_attrs: true } + } AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats | AstFragmentKind::GenericParams | AstFragmentKind::Params | AstFragmentKind::StructFields - | AstFragmentKind::Variants => false, + | AstFragmentKind::Variants => SupportsMacroExpansion::No, } } @@ -408,6 +414,8 @@ kind.article(), kind.descr() ), ); + // FIXME: this workaround issue #84569 + FatalError.raise(); } }; self.cx.trace_macros_diag(); @@ -485,6 +493,7 @@ let fragment_kind = invoc.fragment_kind; let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) { ExpandResult::Ready(fragment) => { + let mut derive_invocations = Vec::new(); let derive_placeholders = self .cx .resolver @@ -506,14 +515,14 @@ _ => unreachable!(), }; - invocations.reserve(derives.len()); + derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(_exts, path)| { + .map(|(path, _exts)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = ExpnId::fresh(None); - invocations.push(( + derive_invocations.push(( Invocation { kind: InvocationKind::Derive { path, @@ -540,7 +549,12 @@ }) .unwrap_or_default(); - self.collect_invocations(fragment, &derive_placeholders) + let (fragment, collected_invocations) = + self.collect_invocations(fragment, &derive_placeholders); + // We choose to expand any derive invocations associated with this macro invocation + // *before* any macro invocations collected from the output fragment + derive_invocations.extend(collected_invocations); + (fragment, derive_invocations) } ExpandResult::Retry(invoc) => { if force { @@ -599,10 +613,15 @@ let invocations = { let mut collector = InvocationCollector { + // Non-derive macro invocations cannot see the results of cfg expansion - they + // will either be removed along with the item, or invoked before the cfg/cfg_attr + // attribute is expanded. Therefore, we don't need to configure the tokens + // Derive macros *can* see the results of cfg-expansion - they are handled + // specially in `fully_expand_fragment` cfg: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features, - modified: false, + config_tokens: false, }, cx: self.cx, invocations: Vec::new(), @@ -697,13 +716,26 @@ SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - let tokens = match attr.style { - AttrStyle::Outer => item.into_tokens(&self.cx.sess.parse_sess), - // FIXME: Properly collect tokens for inner attributes - AttrStyle::Inner => rustc_parse::fake_token_stream( + 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( &self.cx.sess.parse_sess, &item.into_nonterminal(), - ), + ) + } else { + item.into_tokens(&self.cx.sess.parse_sess) }; let attr_item = attr.unwrap_normal_item(); if let MacArgs::Eq(..) = attr_item.args { @@ -729,7 +761,14 @@ }); } }; - fragment_kind.expect_from_annotatables(items) + if fragment_kind == AstFragmentKind::Expr && items.is_empty() { + let msg = + "removing an expression is not supported in this position"; + self.cx.span_err(span, msg); + fragment_kind.dummy(span) + } else { + fragment_kind.expect_from_annotatables(items) + } } Err(mut err) => { err.emit(); @@ -878,21 +917,21 @@ } AstFragmentKind::TraitItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_trait_item()? { + while let Some(item) = this.parse_trait_item(ForceCollect::No)? { items.extend(item); } AstFragment::TraitItems(items) } AstFragmentKind::ImplItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_impl_item()? { + while let Some(item) = this.parse_impl_item(ForceCollect::No)? { items.extend(item); } AstFragment::ImplItems(items) } AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_foreign_item()? { + while let Some(item) = this.parse_foreign_item(ForceCollect::No)? { items.extend(item); } AstFragment::ForeignItems(items) @@ -917,7 +956,7 @@ } AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), AstFragmentKind::Pat => { - AstFragment::Pat(this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?) + AstFragment::Pat(this.parse_pat_allow_top_alt(None, RecoverComma::No)?) } AstFragmentKind::Arms | AstFragmentKind::Fields @@ -1054,13 +1093,23 @@ // since they will not be detected after macro expansion. fn check_attributes(&mut self, attrs: &[ast::Attribute]) { let features = self.cx.ecfg.features.unwrap(); - for attr in attrs.iter() { + let mut attrs = attrs.iter().peekable(); + let mut span: Option = None; + while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); validate_attr::check_meta(&self.cx.sess.parse_sess, attr); + + let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; + span = Some(current_span); + + if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) { + continue; + } + if attr.doc_str().is_some() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( &UNUSED_DOC_COMMENTS, - attr.span, + current_span, ast::CRATE_NODE_ID, "unused doc comment", BuiltinLintDiagnostics::UnusedDocComment(attr.span), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,7 +2,8 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] -#![feature(or_patterns)] +#![feature(iter_zip)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_check.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_check.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_check.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_check.rs 2021-06-17 03:53:50.000000000 +0000 @@ -116,6 +116,8 @@ use smallvec::SmallVec; +use std::iter; + /// Stack represented as linked list. /// /// Those are used for environments because they grow incrementally and are not mutable. @@ -204,7 +206,7 @@ sess.span_diagnostic.span_bug(span, "length mismatch between LHSes and RHSes") } let mut valid = true; - for (lhs, rhs) in lhses.iter().zip(rhses.iter()) { + for (lhs, rhs) in iter::zip(lhses, rhses) { let mut binders = Binders::default(); check_binders(sess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut valid); check_occurrences(sess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut valid); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_rules.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_rules.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_rules.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/macro_rules.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,7 +18,8 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; -use rustc_lint_defs::builtin::SEMICOLON_IN_EXPRESSIONS_FROM_MACROS; +use rustc_lint_defs::builtin::{OR_PATTERNS_BACK_COMPAT, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS}; +use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::parser::Parser; use rustc_session::parse::ParseSess; use rustc_session::Session; @@ -951,8 +952,32 @@ // Now `last` holds the complete set of NT tokens that could // end the sequence before SUFFIX. Check that every one works with `suffix`. for token in &last.tokens { - if let TokenTree::MetaVarDecl(_, name, Some(kind)) = *token { + if let TokenTree::MetaVarDecl(span, name, Some(kind)) = *token { for next_token in &suffix_first.tokens { + // Check if the old pat is used and the next token is `|`. + if let NonterminalKind::PatParam { inferred: true } = kind { + if let TokenTree::Token(token) = next_token { + if let BinOp(token) = token.kind { + if let token::BinOpToken::Or = token { + // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + span, + name, + Some(NonterminalKind::PatParam { inferred: false }), + )); + sess.buffer_lint_with_diagnostic( + &OR_PATTERNS_BACK_COMPAT, + span, + ast::CRATE_NODE_ID, + &*format!("the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",), + BuiltinLintDiagnostics::OrPatternsBackCompat( + span, suggestion, + ), + ); + } + } + } + } match is_in_follow(next_token, kind) { IsInFollow::Yes => {} IsInFollow::No(possible) => { @@ -1080,7 +1105,7 @@ _ => IsInFollow::No(TOKENS), } } - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => { + NonterminalKind::PatParam { .. } => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1088,6 +1113,17 @@ Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes, _ => IsInFollow::No(TOKENS), }, + _ => IsInFollow::No(TOKENS), + } + } + NonterminalKind::PatWithOr { .. } => { + const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; + match tok { + TokenTree::Token(token) => match token.kind { + FatArrow | Comma | Eq => IsInFollow::Yes, + Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes, + _ => IsInFollow::No(TOKENS), + }, _ => IsInFollow::No(TOKENS), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/quoted.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/quoted.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/quoted.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/quoted.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,8 +6,8 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_feature::Features; -use rustc_session::parse::{feature_err, ParseSess}; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_session::parse::ParseSess; +use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; @@ -62,21 +62,6 @@ Some((frag, _)) => { let span = token.span.with_lo(start_sp.lo()); - match frag.name { - sym::pat2018 | sym::pat2021 => { - if !features.edition_macro_pats { - feature_err( - sess, - sym::edition_macro_pats, - frag.span, - "`pat2018` and `pat2021` are unstable.", - ) - .emit(); - } - } - _ => {} - } - let kind = token::NonterminalKind::from_symbol(frag.name, || { span.edition() diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/transcribe.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/transcribe.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe/transcribe.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe/transcribe.rs 2021-06-17 03:53:50.000000000 +0000 @@ -209,7 +209,7 @@ } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` - // is the total number of reptitions we should generate. + // is the total number of repetitions we should generate. repeats.push((0, len)); // The first time we encounter the sequence we push it to the stack. It @@ -362,7 +362,7 @@ /// appropriate meta-vars in `interpolations`. /// /// Note that if `repeats` does not match the exact correct depth of a meta-var, -/// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of +/// `lookup_cur_matched` will return `None`, which is why this still works even in the presence of /// multiple nested matcher sequences. fn lockstep_iter_size( tree: &mbe::TokenTree, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/mbe.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/mbe.rs 2021-06-17 03:53:50.000000000 +0000 @@ -69,7 +69,7 @@ ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions OneOrMore, - /// Kleene optional (`?`) for zero or one reptitions + /// Kleene optional (`?`) for zero or one repetitions ZeroOrOne, } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/proc_macro.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/proc_macro.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/proc_macro.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/proc_macro.rs 2021-06-17 03:53:50.000000000 +0000 @@ -94,7 +94,7 @@ { TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into() } else { - nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes) + nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No) }; let server = proc_macro_server::Rustc::new(ecx); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/proc_macro_server.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/proc_macro_server.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/proc_macro_server.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/proc_macro_server.rs 2021-06-17 03:53:50.000000000 +0000 @@ -739,9 +739,8 @@ let time_macros_impl = macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs"); - if time_macros_impl - || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs")) - { + let js_sys = macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"); + if time_macros_impl || js_sys { let snippet = source_map.span_to_snippet(orig_span); if snippet.as_deref() == Ok("$name") { if time_macros_impl { @@ -754,8 +753,35 @@ "the `time-macros-impl` crate will stop compiling in futures version of Rust. \ Please update to the latest version of the `time` crate to avoid breakage".to_string()) ); + return Some((*ident, *is_raw)); + } + if js_sys { + if let Some(c) = path + .components() + .flat_map(|c| c.as_os_str().to_str()) + .find(|c| c.starts_with("js-sys")) + { + let mut version = c.trim_start_matches("js-sys-").split("."); + if version.next() == Some("0") + && version.next() == Some("3") + && version + .next() + .and_then(|c| c.parse::().ok()) + .map_or(false, |v| v < 40) + { + rustc.sess.buffer_lint_with_diagnostic( + &PROC_MACRO_BACK_COMPAT, + orig_span, + ast::CRATE_NODE_ID, + "using an old version of `js-sys`", + BuiltinLintDiagnostics::ProcMacroBackCompat( + "older versions of the `js-sys` crate will stop compiling in future versions of Rust; \ + please update to `js-sys` v0.3.40 or above".to_string()) + ); + return Some((*ident, *is_raw)); + } + } } - return Some((*ident, *is_raw)); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/tokenstream/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/tokenstream/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_expand/src/tokenstream/tests.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_expand/src/tokenstream/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ use crate::tests::string_to_stream; use rustc_ast::token; -use rustc_ast::tokenstream::{TokenStream, TokenStreamBuilder, TokenTree}; +use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree}; use rustc_span::with_default_session_globals; use rustc_span::{BytePos, Span, Symbol}; use smallvec::smallvec; @@ -14,6 +14,10 @@ Span::with_root_ctxt(BytePos(a), BytePos(b)) } +fn joint(tree: TokenTree) -> TokenStream { + TokenStream::new(vec![(tree, Spacing::Joint)]) +} + #[test] fn test_concat() { with_default_session_globals(|| { @@ -99,8 +103,8 @@ fn test_dotdotdot() { with_default_session_globals(|| { let mut builder = TokenStreamBuilder::new(); - builder.push(TokenTree::token(token::Dot, sp(0, 1)).joint()); - builder.push(TokenTree::token(token::Dot, sp(1, 2)).joint()); + builder.push(joint(TokenTree::token(token::Dot, sp(0, 1)))); + builder.push(joint(TokenTree::token(token::Dot, sp(1, 2)))); builder.push(TokenTree::token(token::Dot, sp(2, 3))); let stream = builder.build(); assert!(stream.eq_unspanned(&string_to_ts("..."))); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/accepted.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/accepted.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/accepted.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/accepted.rs 2021-06-17 03:53:50.000000000 +0000 @@ -276,7 +276,11 @@ /// The smallest useful subset of `const_generics`. (accepted, min_const_generics, "1.51.0", Some(74878), None), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. - (accepted, unsafe_block_in_unsafe_fn, "1.51.0", Some(71668), None), + (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None), + /// Allows the use of or-patterns (e.g., `0 | 1`). + (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows defining identifiers beyond ASCII. + (accepted, non_ascii_idents, "1.53.0", Some(55467), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/active.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/active.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/active.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/active.rs 2021-06-17 03:53:50.000000000 +0000 @@ -63,6 +63,10 @@ _ => panic!("`{}` was not listed in `declare_features`", feature), } } + + pub fn unordered_const_ty_params(&self) -> bool { + self.const_generics || self.const_generics_defaults + } } }; } @@ -134,9 +138,6 @@ /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), - /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. (active, start, "1.0.0", Some(29633), None), @@ -216,6 +217,10 @@ /// Renamed from `optin_builtin_traits`. (active, auto_traits, "1.50.0", Some(13231), None), + /// Allows `#[doc(notable_trait)]`. + /// Renamed from `doc_spotlight`. + (active, doc_notable_trait, "1.52.0", Some(45040), None), + // no-tracking-issue-end // ------------------------------------------------------------------------- @@ -254,12 +259,6 @@ // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using the `#[link_args]` attribute. - (active, link_args, "1.0.0", Some(29596), None), - - /// Allows defining identifiers beyond ASCII. - (active, non_ascii_idents, "1.0.0", Some(55467), None), - /// Allows using `#[plugin_registrar]` on functions. (active, plugin_registrar, "1.0.0", Some(29597), None), @@ -374,9 +373,6 @@ /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - /// Allows `#[doc(spotlight)]`. - (active, doc_spotlight, "1.22.0", Some(45040), None), - /// Allows `#[doc(include = "some-file")]`. (active, external_doc, "1.22.0", Some(44732), None), @@ -488,9 +484,6 @@ /// Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - /// Allows the use of or-patterns (e.g., `0 | 1`). - (active, or_patterns, "1.38.0", Some(54883), None), - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), @@ -614,9 +607,6 @@ /// Allows arbitrary expressions in key-value attributes at parse time. (active, extended_key_value_attributes, "1.50.0", Some(78835), None), - /// `:pat2018` and `:pat2021` macro matchers. - (active, edition_macro_pats, "1.51.0", Some(54883), None), - /// Allows const generics to have default values (e.g. `struct Foo(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), @@ -635,18 +625,34 @@ /// Allows macro attributes to observe output of `#[derive]`. (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), - /// Allows `pub` on `macro_rules` items. - (active, pub_macro_rules, "1.52.0", Some(78855), None), - /// Allows the use of type alias impl trait in function return positions (active, min_type_alias_impl_trait, "1.52.0", Some(63063), None), /// Allows associated types in inherent impls. (active, inherent_associated_types, "1.52.0", Some(8995), None), + // Allows setting the threshold for the `large_assignments` lint. + (active, large_assignments, "1.52.0", Some(83518), None), + /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows `extern "wasm" fn` + (active, wasm_abi, "1.53.0", Some(83788), None), + + /// Allows function attribute `#[no_coverage]`, to bypass coverage + /// instrumentation of that function. + (active, no_coverage, "1.53.0", Some(84605), None), + + /// Allows trait bounds in `const fn`. + (active, const_fn_trait_bound, "1.53.0", Some(57563), None), + + /// Allows unsizing coercions in `const fn`. + (active, const_fn_unsize, "1.53.0", Some(64992), None), + + /// Allows using imported `main` function + (active, imported_main, "1.53.0", Some(28937), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/builtin_attrs.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/builtin_attrs.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/builtin_attrs.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/builtin_attrs.rs 2021-06-17 03:53:50.000000000 +0000 @@ -227,8 +227,8 @@ template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), ), ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), - ungated!(no_link, Normal, template!(Word)), - ungated!(repr, Normal, template!(List: "C")), + ungated!(no_link, AssumedUsed, template!(Word)), + ungated!(repr, AssumedUsed, template!(List: "C")), ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), ungated!(no_mangle, AssumedUsed, template!(Word)), @@ -241,6 +241,10 @@ const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, experimental!(const_eval_limit) ), + gated!( + move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, + experimental!(move_size_limit) + ), // Entry point: ungated!(main, Normal, template!(Word)), @@ -269,6 +273,7 @@ template!(List: "address, memory, thread"), experimental!(no_sanitize) ), + gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)), // FIXME: #14408 assume docs are used since rustdoc looks at them. ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), @@ -280,11 +285,6 @@ // Linking: gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), gated!( - link_args, Normal, template!(NameValueStr: "args"), - "the `link_args` attribute is experimental and not portable across platforms, \ - it is recommended to use `#[link(name = \"foo\")] instead", - ), - gated!( link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, experimental!(link_ordinal) ), @@ -322,7 +322,7 @@ "custom test frameworks are an unstable feature", ), // RFC #1268 - gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), + gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)), gated!( thread_local, AssumedUsed, template!(Word), "`#[thread_local]` is an experimental feature, and does not currently handle destructors", @@ -541,6 +541,15 @@ rustc_specialization_trait, Normal, template!(Word), "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), + rustc_attr!( + rustc_main, Normal, template!(Word), + "the `#[rustc_main]` attribute is used internally to specify test entry point function", + ), + rustc_attr!( + rustc_skip_array_during_method_dispatch, Normal, template!(Word), + "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ + from method dispatch when the receiver is an array, for compatibility in editions < 2021." + ), // ========================================================================== // Internal attributes, Testing: diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ //! # Feature gates //! //! This crate declares the set of past and present unstable features in the compiler. -//! Feature gate checking itself is done in `librustc_ast_passes/feature_gate.rs` +//! Feature gate checking itself is done in `rustc_ast_passes/src/feature_gate.rs` //! at the moment. //! //! Features are enabled in programs via the crate-level attributes of diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/removed.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/removed.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_feature/src/removed.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_feature/src/removed.rs 2021-06-17 03:53:50.000000000 +0000 @@ -80,6 +80,11 @@ Some("subsumed by `#![feature(allocator_internals)]`")), /// Allows identifying crates that contain sanitizer runtimes. (removed, sanitizer_runtime, "1.17.0", None, None, None), + /// Allows `#[doc(spotlight)]`. + /// The attribute was renamed to `#[doc(notable_trait)]` + /// and the feature to `doc_notable_trait`. + (removed, doc_spotlight, "1.22.0", Some(45040), None, + Some("renamed to `doc_notable_trait`")), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, @@ -123,6 +128,14 @@ /// Allows comparing raw pointers during const eval. (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, Some("cannot be allowed in const eval in any meaningful way")), + /// Allows using the `#[link_args]` attribute. + (removed, link_args, "1.53.0", Some(29596), None, + Some("removed in favor of using `-C link-arg=ARG` on command line, \ + which is available from cargo build scripts with `cargo:rustc-link-arg` now")), + /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. + (removed, main, "1.53.0", Some(29634), None, None), + (removed, pub_macro_rules, "1.53.0", Some(78855), None, + Some("removed due to being incomplete, in particular it does not work across crates")), // ------------------------------------------------------------------------- // feature-group-end: removed features diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_graphviz/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_graphviz/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_graphviz/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_graphviz/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -413,10 +413,6 @@ pub fn as_slice(&'a self) -> &'a str { &*self.name } - - pub fn name(self) -> Cow<'a, str> { - self.name - } } /// Each instance of a type that implements `Label` maps to a @@ -484,10 +480,6 @@ LabelStr(s.into()) } - pub fn escaped>>(s: S) -> LabelText<'a> { - EscStr(s.into()) - } - pub fn html>>(s: S) -> LabelText<'a> { HtmlStr(s.into()) } @@ -543,11 +535,6 @@ } } - /// Puts `prefix` on a line above this label, with a blank line separator. - pub fn prefix_line(self, prefix: LabelText<'_>) -> LabelText<'static> { - prefix.suffix_line(self) - } - /// Puts `suffix` on a line below this label, with a blank line separator. pub fn suffix_line(self, suffix: LabelText<'_>) -> LabelText<'static> { let mut prefix = self.pre_escaped_content().into_owned(); @@ -602,11 +589,6 @@ DarkTheme, } -/// Returns vec holding all the default render options. -pub fn default_options() -> Vec { - vec![] -} - /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Simple wrapper around `render_opts` that passes a default set of options.) pub fn render<'a, N, E, G, W>(g: &'a G, w: &mut W) -> io::Result<()> diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_graphviz/src/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_graphviz/src/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_graphviz/src/tests.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_graphviz/src/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -111,7 +111,7 @@ fn node_label(&'a self, n: &Node) -> LabelText<'a> { match self.node_labels[*n] { Some(l) => LabelStr(l.into()), - None => LabelStr(id_name(n).name()), + None => LabelStr(id_name(n).name), } } fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/definitions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/definitions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/definitions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/definitions.rs 2021-06-17 03:53:50.000000000 +0000 @@ -87,6 +87,7 @@ hash } + /// Used by librustdoc for fake DefIds. pub fn num_def_ids(&self) -> usize { self.index_to_key.len() } @@ -319,12 +320,6 @@ self.table.def_path_hash(id.local_def_index) } - #[inline] - pub fn def_path_hash_to_def_id(&self, def_path_hash: DefPathHash) -> LocalDefId { - let local_def_index = self.table.def_path_hash_to_index[&def_path_hash]; - LocalDefId { local_def_index } - } - /// Returns the path from the crate root to `index`. The root /// nodes are not included in the path (i.e., this will be an /// empty vector for the crate root). For an inlined item, this diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/def.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/def.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/def.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/def.rs 2021-06-17 03:53:50.000000000 +0000 @@ -20,6 +20,7 @@ Variant, } +/// What kind of constructor something is. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorKind { @@ -31,6 +32,7 @@ Fictive, } +/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum NonMacroAttrKind { @@ -47,33 +49,51 @@ Registered, } +/// What kind of definition something is; e.g., `mod` vs `struct`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum DefKind { // Type namespace Mod, - /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists. + /// Refers to the struct itself, [`DefKind::Ctor`] refers to its constructor if it exists. Struct, Union, Enum, - /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists. + /// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists. Variant, Trait, - /// `type Foo = Bar;` + /// Type alias: `type Foo = Bar;` TyAlias, + /// Type from an `extern` block. ForeignTy, + /// Trait alias: `trait IntIterator = Iterator;` TraitAlias, + /// Associated type: `trait MyTrait { type Assoc; }` AssocTy, + /// Type parameter: the `T` in `struct Vec { ... }` TyParam, // Value namespace Fn, Const, + /// Constant generic parameter: `struct Foo { ... }` ConstParam, Static, /// Refers to the struct or enum variant's constructor. + /// + /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and + /// [`DefKind::Variant`] is because structs and enum variants exist + /// in the *type* namespace, whereas struct and enum variant *constructors* + /// exist in the *value* namespace. + /// + /// You may wonder why enum variants exist in the type namespace as opposed + /// to the value namespace. Check out [RFC 2593] for intuition on why that is. + /// + /// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593 Ctor(CtorOf, CtorKind), + /// Associated function: `impl MyStruct { fn associated() {} }` AssocFn, + /// Associated constant: `trait MyTrait { const ASSOC: usize; }` AssocConst, // Macro namespace @@ -82,11 +102,16 @@ // Not namespaced (or they are, but we don't treat them so) ExternCrate, Use, + /// An `extern` block. ForeignMod, + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}` AnonConst, + /// Opaque type, aka `impl Trait`. OpaqueTy, Field, + /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, + /// A use of [`global_asm!`]. GlobalAsm, Impl, Closure, @@ -196,35 +221,130 @@ } /// The resolution of a path or export. +/// +/// For every path or identifier in Rust, the compiler must determine +/// what the path refers to. This process is called name resolution, +/// and `Res` is the primary result of name resolution. +/// +/// For example, everything prefixed with `/* Res */` in this example has +/// an associated `Res`: +/// +/// ``` +/// fn str_to_string(s: & /* Res */ str) -> /* Res */ String { +/// /* Res */ String::from(/* Res */ s) +/// } +/// +/// /* Res */ str_to_string("hello"); +/// ``` +/// +/// The associated `Res`s will be: +/// +/// - `str` will resolve to [`Res::PrimTy`]; +/// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`] +/// for `String` as defined in the standard library; +/// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`] +/// pointing to `String::from`; +/// - `s` will resolve to [`Res::Local`]; +/// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] +/// pointing to the definition of `str_to_string` in the current crate. +// #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum Res { + /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. + /// + /// **Not bound to a specific namespace.** Def(DefKind, DefId), // Type namespace + /// A primitive type such as `i32` or `str`. + /// + /// **Belongs to the type namespace.** PrimTy(hir::PrimTy), - /// `Self`, with both an optional trait and impl `DefId`. + /// The `Self` type, optionally with the trait it is associated with + /// and optionally with the [`DefId`] of the impl it is associated with. + /// + /// **Belongs to the type namespace.** + /// + /// For example, the `Self` in /// - /// HACK(min_const_generics): impl self types also have an optional requirement to not mention + /// ``` + /// trait Foo { + /// fn foo() -> Box; + /// } + /// ``` + /// + /// would have the [`DefId`] of `Foo` associated with it. The `Self` in + /// + /// ``` + /// struct Bar; + /// + /// impl Bar { + /// fn new() -> Self { Bar } + /// } + /// ``` + /// + /// would have the [`DefId`] of the impl associated with it. Finally, the `Self` in + /// + /// ``` + /// impl Foo for Bar { + /// fn foo() -> Box { Box::new(Bar) } + /// } + /// ``` + /// + /// would have both the [`DefId`] of `Foo` and the [`DefId`] of the impl + /// associated with it. + /// + /// *See also [`Res::SelfCtor`].* + /// + /// ----- + /// + /// HACK(min_const_generics): impl self types also have an optional requirement to **not** mention /// any generic parameters to allow the following with `min_const_generics`: - /// ```rust - /// impl Foo { fn test() -> [u8; std::mem::size_of::()] {} } + /// ``` + /// impl Foo { fn test() -> [u8; std::mem::size_of::()] { todo!() } } /// ``` /// We do however allow `Self` in repeat expression even if it is generic to not break code /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint. /// /// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable. - SelfTy(Option /* trait */, Option<(DefId, bool)> /* impl */), - ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` + SelfTy( + /// Optionally, the trait associated with this `Self` type. + Option, + /// Optionally, the impl associated with this `Self` type. + Option<(DefId, bool)>, + ), + /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`. + /// + /// **Belongs to the type namespace.** + ToolMod, // Value namespace - SelfCtor(DefId /* impl */), // `DefId` refers to the impl + /// The `Self` constructor, along with the [`DefId`] + /// of the impl it is associated with. + /// + /// **Belongs to the value namespace.** + /// + /// *See also [`Res::SelfTy`].* + SelfCtor(DefId), + /// A local variable or function parameter. + /// + /// **Belongs to the value namespace.** Local(Id), // Macro namespace + /// An attribute that is *not* implemented via macro. + /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives, + /// as opposed to `#[test]`, which is a builtin macro. + /// + /// **Belongs to the macro namespace.** NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` // All namespaces + /// Name resolution failed. We use a dummy `Res` variant so later phases + /// of the compiler won't crash and can instead report more errors. + /// + /// **Not bound to a specific namespace.** Err, } @@ -275,17 +395,26 @@ } } -/// Different kinds of symbols don't influence each other. -/// -/// Therefore, they have a separate universe (namespace). +/// Different kinds of symbols can coexist even if they share the same textual name. +/// Therefore, they each have a separate universe (known as a "namespace"). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum Namespace { + /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s + /// (and, by extension, crates). + /// + /// Note that the type namespace includes other items; this is not an + /// exhaustive list. TypeNS, + /// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments). ValueNS, + /// The macro namespace includes `macro_rules!` macros, declarative `macro`s, + /// procedural macros, attribute macros, `derive` macros, and non-macro attributes + /// like `#[inline]` and `#[rustfmt::skip]`. MacroNS, } impl Namespace { + /// The English description of the namespace. pub fn descr(self) -> &'static str { match self { Self::TypeNS => "type", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/hir_id.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/hir_id.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/hir_id.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/hir_id.rs 2021-06-17 03:53:50.000000000 +0000 @@ -63,6 +63,7 @@ local_id: ItemLocalId::from_u32(0), }; +/// N.B. This collection is currently unused, but will be used by #72015 and future PRs. #[derive(Clone, Default, Debug, Encodable, Decodable)] pub struct HirIdVec { map: IndexVec>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/hir.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/hir.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/hir.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/hir.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,5 @@ // ignore-tidy-filelength -use crate::def::{CtorKind, DefKind, Namespace, Res}; +use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::DefId; crate use crate::hir_id::HirId; use crate::{itemlikevisit, LangItem}; @@ -296,7 +296,9 @@ match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + GenericArg::Const(_) => { + ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } + } } } } @@ -402,7 +404,7 @@ /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -625,13 +627,6 @@ pub foreign_items: BTreeSet, } -/// A type representing only the top-level module. -#[derive(Encodable, Debug, HashStable_Generic)] -pub struct CrateItem<'hir> { - pub module: Mod<'hir>, - pub span: Span, -} - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -640,7 +635,7 @@ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - pub item: CrateItem<'hir>, + pub item: Mod<'hir>, pub exported_macros: &'hir [MacroDef<'hir>], // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: &'hir [Attribute], @@ -2118,15 +2113,6 @@ TyAlias(&'hir Ty<'hir>), } -impl ImplItemKind<'_> { - pub fn namespace(&self) -> Namespace { - match self { - ImplItemKind::TyAlias(..) => Namespace::TypeNS, - ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS, - } - } -} - // The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; @@ -2215,6 +2201,9 @@ Self::Str, ]; + /// Like [`PrimTy::name`], but returns a &str instead of a symbol. + /// + /// Used by clippy. pub fn name_str(self) -> &'static str { match self { PrimTy::Int(i) => i.name_str(), @@ -2360,7 +2349,7 @@ out_expr: Option>, }, Const { - expr: Expr<'hir>, + anon_const: AnonConst, }, Sym { expr: Expr<'hir>, @@ -2569,7 +2558,7 @@ /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the /// trait being referred to but just a unique `HirId` that serves as a key /// within the resolution map. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct TraitRef<'hir> { pub path: &'hir Path<'hir>, // Don't hash the `ref_id`. It is tracked via the thing it is used to access. @@ -2588,7 +2577,7 @@ } } -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], @@ -2989,7 +2978,7 @@ GenericParam(&'hir GenericParam<'hir>), Visibility(&'hir Visibility<'hir>), - Crate(&'hir CrateItem<'hir>), + Crate(&'hir Mod<'hir>), } impl<'hir> Node<'hir> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/intravisit.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/intravisit.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/intravisit.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/intravisit.rs 2021-06-17 03:53:50.000000000 +0000 @@ -98,7 +98,7 @@ } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>), @@ -366,6 +366,9 @@ fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) { walk_generic_param(self, p) } + fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) { + walk_const_param_default(self, ct) + } fn visit_generics(&mut self, g: &'v Generics<'v>) { walk_generics(self, g) } @@ -475,7 +478,7 @@ /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); + visitor.visit_mod(&krate.item, krate.item.inner, CRATE_HIR_ID); walk_list!(visitor, visit_macro_def, krate.exported_macros); for (&id, attrs) in krate.attrs.iter() { for a in *attrs { @@ -869,13 +872,17 @@ GenericParamKind::Const { ref ty, ref default } => { visitor.visit_ty(ty); if let Some(ref default) = default { - visitor.visit_anon_const(default); + visitor.visit_const_param_default(param.hir_id, default); } } } walk_list!(visitor, visit_param_bound, param.bounds); } +pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) { + visitor.visit_anon_const(ct) +} + pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) { walk_list!(visitor, visit_generic_param, generics.params); walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates); @@ -1182,7 +1189,6 @@ match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -1195,6 +1201,9 @@ visitor.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => { + visitor.visit_anon_const(anon_const) + } } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,12 +3,11 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] -#![feature(const_fn)] // For the unsizing cast on `&[]` #![feature(const_panic)] #![feature(extended_key_value_attributes)] #![feature(in_band_lifetimes)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/pat_util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/pat_util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/pat_util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/pat_util.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,7 @@ use crate::def::{CtorOf, DefKind, Res}; use crate::def_id::DefId; use crate::hir::{self, HirId, PatKind}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -89,26 +90,6 @@ }) } - /// Checks if the pattern contains any patterns that bind something to - /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. - pub fn contains_bindings(&self) -> bool { - self.satisfies(|p| matches!(p.kind, PatKind::Binding(..))) - } - - /// Checks if the pattern satisfies the given predicate on some sub-pattern. - fn satisfies(&self, pred: impl Fn(&hir::Pat<'_>) -> bool) -> bool { - let mut satisfies = false; - self.walk_short(|p| { - if pred(p) { - satisfies = true; - false // Found one, can short circuit now. - } else { - true - } - }); - satisfies - } - pub fn simple_ident(&self) -> Option { match self.kind { PatKind::Binding( @@ -138,8 +119,10 @@ } _ => true, }); - variants.sort(); - variants.dedup(); + // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering + // the bounds + let mut duplicates = FxHashSet::default(); + variants.retain(|def_id| duplicates.insert(*def_id)); variants } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/stable_hash_impls.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/stable_hash_impls.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/stable_hash_impls.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/stable_hash_impls.rs 2021-06-17 03:53:50.000000000 +0000 @@ -9,7 +9,7 @@ /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext: rustc_ast::HashStableContext + rustc_target::HashStableContext { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/weak_lang_items.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/weak_lang_items.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir/src/weak_lang_items.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir/src/weak_lang_items.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,8 +18,8 @@ map }); -/// The `check_name` argument avoids the need for `librustc_hir` to depend on -/// `librustc_session`. +/// The `check_name` argument avoids the need for `rustc_hir` to depend on +/// `rustc_session`. pub fn link_name<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option where F: Fn(&'a ast::Attribute, Symbol) -> bool diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir_pretty/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir_pretty/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_hir_pretty/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_hir_pretty/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,4 @@ -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] use rustc_ast as ast; @@ -170,7 +170,7 @@ // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(&krate.item.module, s.attrs(hir::CRATE_HIR_ID)); + s.print_mod(&krate.item, s.attrs(hir::CRATE_HIR_ID)); s.print_remaining_comments(); s.s.eof() } @@ -221,10 +221,6 @@ to_string(NO_ANN, |s| s.print_bounds("", bounds)) } -pub fn param_to_string(arg: &hir::Param<'_>) -> String { - to_string(NO_ANN, |s| s.print_param(arg)) -} - pub fn ty_to_string(ty: &hir::Ty<'_>) -> String { to_string(NO_ANN, |s| s.print_type(ty)) } @@ -1099,8 +1095,8 @@ fn print_else(&mut self, els: Option<&hir::Expr<'_>>) { match els { - Some(_else) => { - match _else.kind { + Some(else_) => { + match else_.kind { // "another else-if" hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); @@ -1118,6 +1114,26 @@ self.s.word(" else "); self.print_block(&b) } + hir::ExprKind::Match(ref expr, arms, _) => { + // else if let desugared to match + assert!(arms.len() == 2, "if let desugars to match with two arms"); + + self.s.word(" else "); + self.s.word("{"); + + self.cbox(INDENT_UNIT); + self.ibox(INDENT_UNIT); + self.word_nbsp("match"); + self.print_expr_as_cond(&expr); + self.s.space(); + self.bopen(); + for arm in arms { + self.print_arm(arm); + } + self.bclose(expr.span); + + self.s.word("}"); + } // BLEAH, constraints would be great here _ => { panic!("print_if saw if with weird alternative"); @@ -1574,10 +1590,10 @@ None => s.word("_"), } } - hir::InlineAsmOperand::Const { expr } => { + hir::InlineAsmOperand::Const { anon_const } => { s.word("const"); s.space(); - s.print_expr(expr); + s.print_anon_const(anon_const); } hir::InlineAsmOperand::Sym { expr } => { s.word("sym"); @@ -1701,21 +1717,10 @@ } } - pub fn print_usize(&mut self, i: usize) { - self.s.word(i.to_string()) - } - pub fn print_name(&mut self, name: Symbol) { self.print_ident(Ident::with_dummy_span(name)) } - pub fn print_for_decl(&mut self, loc: &hir::Local<'_>, coll: &hir::Expr<'_>) { - self.print_local_decl(loc); - self.s.space(); - self.word_space("in"); - self.print_expr(coll) - } - pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) { self.maybe_print_comment(path.span.lo()); @@ -2266,8 +2271,10 @@ GenericParamKind::Const { ref ty, ref default } => { self.word_space(":"); self.print_type(ty); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { + self.s.space(); + self.word_space("="); + self.print_anon_const(&default) } } } @@ -2428,24 +2435,6 @@ } } - pub fn print_opt_abi_and_extern_if_nondefault(&mut self, opt_abi: Option) { - match opt_abi { - Some(Abi::Rust) => {} - Some(abi) => { - self.word_nbsp("extern"); - self.word_nbsp(abi.to_string()) - } - None => {} - } - } - - pub fn print_extern_opt_abi(&mut self, opt_abi: Option) { - if let Some(abi) = opt_abi { - self.word_nbsp("extern"); - self.word_nbsp(abi.to_string()) - } - } - pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { self.s.word(visibility_qualified(vis, "")); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/assert_dep_graph.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/assert_dep_graph.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/assert_dep_graph.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/assert_dep_graph.rs 2021-06-17 03:53:50.000000000 +0000 @@ -40,8 +40,9 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_middle::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -use rustc_middle::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt}; +use rustc_middle::dep_graph::{ + DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, +}; use rustc_middle::hir::map::Map; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -54,7 +55,11 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.debugging_opts.dump_dep_graph { - dump_graph(tcx); + tcx.dep_graph.with_query(dump_graph); + } + + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; } // if the `rustc_attrs` feature is not enabled, then the @@ -196,29 +201,29 @@ } return; } - let query = tcx.dep_graph.query(); - for &(_, source_def_id, ref source_dep_node) in if_this_changed { - let dependents = query.transitive_predecessors(source_dep_node); - for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { - if !dependents.contains(&target_dep_node) { - tcx.sess.span_err( - target_span, - &format!( - "no path from `{}` to `{}`", - tcx.def_path_str(source_def_id), - target_pass - ), - ); - } else { - tcx.sess.span_err(target_span, "OK"); + tcx.dep_graph.with_query(|query| { + for &(_, source_def_id, ref source_dep_node) in if_this_changed { + let dependents = query.transitive_predecessors(source_dep_node); + for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { + if !dependents.contains(&target_dep_node) { + tcx.sess.span_err( + target_span, + &format!( + "no path from `{}` to `{}`", + tcx.def_path_str(source_def_id), + target_pass + ), + ); + } else { + tcx.sess.span_err(target_span, "OK"); + } } } - } + }); } -fn dump_graph(tcx: TyCtxt<'_>) { +fn dump_graph(query: &DepGraphQuery) { let path: String = env::var("RUST_DEP_GRAPH").unwrap_or_else(|_| "dep_graph".to_string()); - let query = tcx.dep_graph.query(); let nodes = match env::var("RUST_DEP_GRAPH_FILTER") { Ok(string) => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,7 +14,7 @@ pub mod assert_module_sources; mod persist; -pub use assert_dep_graph::assert_dep_graph; +use assert_dep_graph::assert_dep_graph; pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir; pub use persist::delete_workproduct_files; pub use persist::finalize_session_directory; @@ -26,4 +26,4 @@ pub use persist::save_dep_graph; pub use persist::save_work_product_index; pub use persist::LoadResult; -pub use persist::{load_dep_graph, DepGraphFuture}; +pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture}; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/dirty_clean.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,7 +14,6 @@ //! the required condition is not met. use rustc_ast::{self as ast, Attribute, NestedMetaItem}; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -74,16 +73,6 @@ &[label_strs::generics_of, label_strs::predicates_of, label_strs::type_of]; /// Trait definition `DepNode`s. -const BASE_TRAIT_DEF: &[&str] = &[ - label_strs::associated_item_def_ids, - label_strs::generics_of, - label_strs::object_safety_violations, - label_strs::predicates_of, - label_strs::specialization_graph_of, - label_strs::trait_def, - label_strs::trait_impls_of, -]; - /// Extra `DepNode`s for functions and methods. const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item]; @@ -118,10 +107,6 @@ /// Abstract data type (struct, enum, union) `DepNode`s. const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; -/// Trait definition `DepNode`s. -#[allow(dead_code)] -const LABELS_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_TRAIT_DEF]; - // FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these) // // Fields are kind of separate from their containers, as they can change independently from @@ -148,6 +133,10 @@ } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; + } + // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.features().rustc_attrs { return; @@ -391,10 +380,7 @@ fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - let current_fingerprint = self.get_fingerprint(&dep_node); - let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - - if current_fingerprint == prev_fingerprint { + if self.tcx.dep_graph.is_green(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess @@ -402,28 +388,10 @@ } } - fn get_fingerprint(&self, dep_node: &DepNode) -> Option { - if self.tcx.dep_graph.dep_node_exists(dep_node) { - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node); - Some(self.tcx.dep_graph.fingerprint_of(dep_node_index)) - } else { - None - } - } - fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - let current_fingerprint = self.get_fingerprint(&dep_node); - let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - - // if the node wasn't previously evaluated and now is (or vice versa), - // then the node isn't actually clean or dirty. - if (current_fingerprint == None) ^ (prev_fingerprint == None) { - return; - } - - if current_fingerprint != prev_fingerprint { + if self.tcx.dep_graph.is_red(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/file_format.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/file_format.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/file_format.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/file_format.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,6 +15,7 @@ use std::path::Path; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; +use rustc_serialize::Encoder; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/fs.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/fs.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/fs.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/fs.rs 2021-06-17 03:53:50.000000000 +0000 @@ -122,6 +122,7 @@ const LOCK_FILE_EXT: &str = ".lock"; const DEP_GRAPH_FILENAME: &str = "dep-graph.bin"; +const STAGING_DEP_GRAPH_FILENAME: &str = "dep-graph.part.bin"; const WORK_PRODUCTS_FILENAME: &str = "work-products.bin"; const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; @@ -134,6 +135,9 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { + in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) +} pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf { in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/load.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/load.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/load.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/load.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,7 +5,7 @@ use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::query::OnDiskCache; use rustc_serialize::opaque::Decoder; -use rustc_serialize::Decodable as RustcDecodable; +use rustc_serialize::Decodable; use rustc_session::Session; use std::path::Path; @@ -104,7 +104,7 @@ // Fortunately, we just checked that this isn't the case. let path = dep_graph_path_from(&sess.incr_comp_session_dir()); let report_incremental_info = sess.opts.debugging_opts.incremental_info; - let expected_hash = sess.opts.dep_tracking_hash(); + let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = FxHashMap::default(); let nightly_build = sess.is_nightly_build(); @@ -120,7 +120,7 @@ // Decode the list of work_products let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos); let work_products: Vec = - RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| { + Decodable::decode(&mut work_product_decoder).unwrap_or_else(|e| { let msg = format!( "Error decoding `work-products` from incremental \ compilation session directory: {}", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,6 +18,7 @@ pub use load::load_query_result_cache; pub use load::LoadResult; pub use load::{load_dep_graph, DepGraphFuture}; +pub use save::build_dep_graph; pub use save::save_dep_graph; pub use save::save_work_product_index; pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/save.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/save.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_incremental/src/persist/save.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_incremental/src/persist/save.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; -use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{DepGraph, PreviousDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encodable as RustcEncodable; @@ -15,6 +15,9 @@ use super::fs::*; use super::work_product; +/// Save and dump the DepGraph. +/// +/// No query must be invoked after this function. pub fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { @@ -29,6 +32,14 @@ let query_cache_path = query_cache_path(sess); let dep_graph_path = dep_graph_path(sess); + let staging_dep_graph_path = staging_dep_graph_path(sess); + + sess.time("assert_dep_graph", || crate::assert_dep_graph(tcx)); + sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)); + + if sess.opts.debugging_opts.incremental_info { + tcx.dep_graph.print_incremental_info() + } join( move || { @@ -36,16 +47,26 @@ save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e)); }); }, - || { + move || { sess.time("incr_comp_persist_dep_graph", || { - save_in(sess, dep_graph_path, "dependency graph", |e| { - sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e)) - }); + if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) { + sess.err(&format!( + "failed to write dependency graph to `{}`: {}", + staging_dep_graph_path.display(), + err + )); + } + if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { + sess.err(&format!( + "failed to move dependency graph from `{}` to `{}`: {}", + staging_dep_graph_path.display(), + dep_graph_path.display(), + err + )); + } }); }, ); - - dirty_clean::check_dirty_clean_annotations(tcx); }) } @@ -92,7 +113,7 @@ }); } -fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) +pub(crate) fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) where F: FnOnce(&mut FileEncoder) -> FileEncodeResult, { @@ -144,21 +165,6 @@ debug!("save: data written to disk successfully"); } -fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult { - // First encode the commandline arguments hash - tcx.sess.opts.dep_tracking_hash().encode(encoder)?; - - if tcx.sess.opts.debugging_opts.incremental_info { - tcx.dep_graph.print_incremental_info(); - } - - // There is a tiny window between printing the incremental info above and encoding the dep - // graph below in which the dep graph could change, thus making the printed incremental info - // slightly out of date. If this matters to you, please feel free to submit a patch. :) - - tcx.sess.time("incr_comp_encode_serialized_dep_graph", || tcx.dep_graph.encode(encoder)) -} - fn encode_work_product_index( work_products: &FxHashMap, encoder: &mut FileEncoder, @@ -177,3 +183,56 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult { tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) } + +pub fn build_dep_graph( + sess: &Session, + prev_graph: PreviousDepGraph, + prev_work_products: FxHashMap, +) -> Option { + if sess.opts.incremental.is_none() { + // No incremental compilation. + return None; + } + + // Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors. + let path_buf = staging_dep_graph_path(sess); + + let mut encoder = match FileEncoder::new(&path_buf) { + Ok(encoder) => encoder, + Err(err) => { + sess.err(&format!( + "failed to create dependency graph at `{}`: {}", + path_buf.display(), + err + )); + return None; + } + }; + + if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) { + sess.err(&format!( + "failed to write dependency graph header to `{}`: {}", + path_buf.display(), + err + )); + return None; + } + + // First encode the commandline arguments hash + if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) { + sess.err(&format!( + "failed to write dependency graph hash `{}`: {}", + path_buf.display(), + err + )); + return None; + } + + Some(DepGraph::new( + prev_graph, + prev_work_products, + encoder, + sess.opts.debugging_opts.query_dep_graph, + sess.opts.debugging_opts.incremental_info, + )) +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -8,6 +8,6 @@ doctest = false [dependencies] -arrayvec = { version = "0.5.1", default-features = false } +arrayvec = { version = "0.7", default-features = false } rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/bit_set.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/bit_set.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/bit_set.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/bit_set.rs 2021-06-17 03:53:50.000000000 +0000 @@ -356,7 +356,7 @@ { assert_eq!(out_vec.len(), in_vec.len()); let mut changed = false; - for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + for (out_elem, in_elem) in iter::zip(out_vec, in_vec) { let old_val = *out_elem; let new_val = op(old_val, *in_elem); *out_elem = new_val; @@ -375,7 +375,7 @@ #[derive(Clone, Debug)] pub struct SparseBitSet { domain_size: usize, - elems: ArrayVec<[T; SPARSE_MAX]>, + elems: ArrayVec, } impl SparseBitSet { @@ -842,7 +842,7 @@ let (write_start, write_end) = self.range(write); let words = &mut self.words[..]; let mut changed = false; - for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(read_start..read_end, write_start..write_end) { let word = words[write_index]; let new_word = word | words[read_index]; words[write_index] = new_word; @@ -858,7 +858,7 @@ assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in (0..with.words().len()).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { let word = self.words[write_index]; let new_word = word | with.words()[read_index]; self.words[write_index] = new_word; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,8 @@ #![feature(allow_internal_unstable)] -#![feature(const_fn)] +#![feature(bench_black_box)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/vec.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/vec.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_index/src/vec.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_index/src/vec.rs 2021-06-17 03:53:50.000000000 +0000 @@ -124,7 +124,8 @@ #[inline] $v const fn from_usize(value: usize) -> Self { - assert!(value <= ($max as usize)); + // FIXME: replace with `assert!(value <= ($max as usize));` once `const_panic` is stable + [()][(value > ($max as usize)) as usize]; unsafe { Self::from_u32_unchecked(value as u32) } @@ -132,7 +133,8 @@ #[inline] $v const fn from_u32(value: u32) -> Self { - assert!(value <= $max); + // FIXME: replace with `assert!(value <= $max);` once `const_panic` is stable + [()][(value > $max) as usize]; unsafe { Self::from_u32_unchecked(value) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs 2021-06-17 03:53:50.000000000 +0000 @@ -293,7 +293,7 @@ self.tcx } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -621,7 +621,7 @@ r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) }; let region = ty::ReLateBound(self.binder_index, br); self.tcx().mk_region(region) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/query_response.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/query_response.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/query_response.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/query_response.rs 2021-06-17 03:53:50.000000000 +0000 @@ -27,6 +27,7 @@ use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; use std::fmt::Debug; +use std::iter; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// This method is meant to be invoked as the final step of a canonical query @@ -418,7 +419,8 @@ // In terms of our example above, we are iterating over pairs like: // [(?A, Vec), ('static, '?1), (?B, ?0)] - for (original_value, result_value) in original_values.var_values.iter().zip(result_values) { + for (original_value, result_value) in iter::zip(&original_values.var_values, result_values) + { match result_value.unpack() { GenericArgKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... @@ -437,7 +439,7 @@ // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.assert_bound_var()] = Some(*original_value); + opt_values[br.var] = Some(*original_value); } } GenericArgKind::Const(result_value) => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/substitute.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/substitute.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/substitute.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/canonical/substitute.rs 2021-06-17 03:53:50.000000000 +0000 @@ -71,11 +71,10 @@ if var_values.var_values.is_empty() { value } else { - let fld_r = - |br: ty::BoundRegion| match var_values.var_values[br.assert_bound_var()].unpack() { - GenericArgKind::Lifetime(l) => l, - r => bug!("{:?} is a region but value is {:?}", br, r), - }; + let fld_r = |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { + GenericArgKind::Lifetime(l) => l, + r => bug!("{:?} is a region but value is {:?}", br, r), + }; let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { GenericArgKind::Type(ty) => ty, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/combine.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/combine.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/combine.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/combine.rs 2021-06-17 03:53:50.000000000 +0000 @@ -191,7 +191,7 @@ /// /// This also tests if the given const `ct` contains an inference variable which was previously /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` - /// would result in an infinite type as we continously replace an inference variable + /// would result in an infinite type as we continuously replace an inference variable /// in `ct` with `ct` itself. /// /// This is especially important as unevaluated consts use their parents generics. @@ -543,15 +543,11 @@ true } - fn visit_ct_substs(&self) -> bool { - true - } - fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -737,6 +733,16 @@ } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } @@ -822,10 +828,6 @@ true } - fn visit_ct_substs(&self) -> bool { - true - } - fn relate_with_variance>( &mut self, _variance: ty::Variance, @@ -838,9 +840,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -959,6 +961,16 @@ } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/equate.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/equate.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/equate.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/equate.rs 2021-06-17 03:53:50.000000000 +0000 @@ -124,9 +124,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -67,13 +67,13 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, - subst::{Subst, SubstsRef}, + subst::{GenericArgKind, Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::ControlFlow; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; mod note; @@ -514,7 +514,7 @@ fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Err(NonTrivialPath) } @@ -957,33 +957,27 @@ ) -> SubstsRef<'tcx> { let generics = self.tcx.generics_of(def_id); let mut num_supplied_defaults = 0; - let mut type_params = generics - .params - .iter() - .rev() - .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { has_default, .. } => { - Some((param.def_id, has_default)) - } - ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults) - }) - .peekable(); - let has_default = { - let has_default = type_params.peek().map(|(_, has_default)| has_default); - *has_default.unwrap_or(&false) - }; - if has_default { - let types = substs.types().rev(); - for ((def_id, has_default), actual) in type_params.zip(types) { - if !has_default { - break; + + let default_params = generics.params.iter().rev().filter_map(|param| match param.kind { + ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id), + ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id), + _ => None, + }); + for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) { + match actual.unpack() { + GenericArgKind::Const(c) => { + if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c { + break; + } } - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; + GenericArgKind::Type(ty) => { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty { + break; + } } - num_supplied_defaults += 1; + _ => break, } + num_supplied_defaults += 1; } let len = generics.params.len(); let mut generics = generics.clone(); @@ -1046,7 +1040,7 @@ let len1 = sig1.inputs().len(); let len2 = sig2.inputs().len(); if len1 == len2 { - for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() { + for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() { let (x1, x2) = self.cmp(l, r); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); @@ -1167,12 +1161,10 @@ let common_len = cmp::min(len1, len2); let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); - let common_default_params = remainder1 - .iter() - .rev() - .zip(remainder2.iter().rev()) - .filter(|(a, b)| a == b) - .count(); + let common_default_params = + iter::zip(remainder1.iter().rev(), remainder2.iter().rev()) + .filter(|(a, b)| a == b) + .count(); let len = sub1.len() - common_default_params; let consts_offset = len - sub1.consts().count(); @@ -1303,12 +1295,11 @@ const SEPARATOR: &str = "::"; let separator_len = SEPARATOR.len(); - let split_idx: usize = t1_str - .split(SEPARATOR) - .zip(t2_str.split(SEPARATOR)) - .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) - .map(|(mod_str, _)| mod_str.len() + separator_len) - .sum(); + let split_idx: usize = + iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR)) + .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) + .map(|(mod_str, _)| mod_str.len() + separator_len) + .sum(); debug!( "cmp: separator_len={}, split_idx={}, min_len={}", @@ -1913,7 +1904,9 @@ .find_map(|(path, msg)| (&path_str == path).then_some(msg)) { let mut show_suggestion = true; - for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { + for (exp_ty, found_ty) in + iter::zip(exp_substs.types(), found_substs.types()) + { match *exp_ty.kind() { ty::Ref(_, exp_ty, _) => { match (exp_ty.kind(), found_ty.kind()) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs 2021-06-17 03:53:50.000000000 +0000 @@ -287,6 +287,7 @@ pub struct InferenceDiagnosticsParentData { pub prefix: &'static str, pub name: String, + pub def_id: DefId, } pub enum UnderspecifiedArgKind { @@ -328,6 +329,7 @@ Some(InferenceDiagnosticsParentData { prefix: tcx.def_kind(parent_def_id).descr(parent_def_id), name: parent_name, + def_id: parent_def_id, }) } } @@ -754,12 +756,30 @@ if let (UnderspecifiedArgKind::Const { .. }, Some(parent_data)) = (&arg_data.kind, &arg_data.parent) { - err.span_suggestion_verbose( - span, - "consider specifying the const argument", - format!("{}::<{}>", parent_data.name, arg_data.name), - Applicability::MaybeIncorrect, - ); + let has_impl_trait = + self.tcx.generics_of(parent_data.def_id).params.iter().any(|param| { + matches!( + param.kind, + ty::GenericParamDefKind::Type { + synthetic: Some( + hir::SyntheticTyParamKind::ImplTrait + | hir::SyntheticTyParamKind::FromAttr, + ), + .. + } + ) + }); + + // (#83606): Do not emit a suggestion if the parent has an `impl Trait` + // as an argument otherwise it will cause the E0282 error. + if !has_impl_trait { + err.span_suggestion_verbose( + span, + "consider specifying the const argument", + format!("{}::<{}>", parent_data.name, arg_data.name), + Applicability::MaybeIncorrect, + ); + } } err.span_label( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs 2021-06-17 03:53:50.000000000 +0000 @@ -115,7 +115,7 @@ // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), ty::BrAnon(br_index), ) => { debug!( @@ -143,7 +143,7 @@ // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBound(debruijn_index, id, _)), + Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _), ) => { debug!( @@ -162,8 +162,8 @@ rl::Region::Static | rl::Region::Free(_, _) | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _), + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _), ) | None, _, @@ -217,7 +217,10 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { match (self.tcx.named_region(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => { + ( + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), + ty::BrAnon(br_index), + ) => { if debruijn_index == self.current_index && anon_index == br_index { self.found_it = true; return; @@ -232,7 +235,7 @@ } } - (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => { + (Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _)) => { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); @@ -246,8 +249,8 @@ Some( rl::Region::Static | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _) + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _) | rl::Region::Free(_, _), ) | None, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/glb.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/glb.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/glb.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/glb.rs 2021-06-17 03:53:50.000000000 +0000 @@ -85,9 +85,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/higher_ranked/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/higher_ranked/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/higher_ranked/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/higher_ranked/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,10 +11,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub( &mut self, - a: Binder, - b: Binder, + a: Binder<'tcx, T>, + b: Binder<'tcx, T>, a_is_expected: bool, - ) -> RelateResult<'tcx, Binder> + ) -> RelateResult<'tcx, Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -50,7 +50,10 @@ debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder::bind(result)) + // We related `a_prime` and `b_prime`, which just had any bound vars + // replaced with placeholders or infer vars, respectively. Relating + // them should not introduce new bound vars. + Ok(ty::Binder::dummy(result)) }) } } @@ -66,7 +69,7 @@ /// the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder) -> T + pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/lub.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/lub.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/lub.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/lub.rs 2021-06-17 03:53:50.000000000 +0000 @@ -85,9 +85,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,7 +18,6 @@ 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; use rustc_middle::mir::interpret::EvalToConstValueResult; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -1267,15 +1266,6 @@ self.resolve_vars_if_possible(t).to_string() } - pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String { - let tstrs: Vec = ts.iter().map(|t| self.ty_to_string(*t)).collect(); - format!("({})", tstrs.join(", ")) - } - - pub fn trait_ref_to_string(&self, t: ty::TraitRef<'tcx>) -> String { - self.resolve_vars_if_possible(t).print_only_trait_path().to_string() - } - /// If `TyVar(vid)` resolves to a type, return that type. Else, return the /// universe index of `TyVar(vid)`. pub fn probe_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { @@ -1416,7 +1406,7 @@ &self, span: Span, lbrct: LateBoundRegionConversionTime, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> (T, BTreeMap>) where T: TypeFoldable<'tcx>, @@ -1499,9 +1489,7 @@ pub fn const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, - promoted: Option, + ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { let mut original_values = OriginalQueryValues::default(); @@ -1510,7 +1498,7 @@ let (param_env, substs) = 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, def, substs, promoted, span) + self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span) } /// If `typ` is a type variable of some kind, resolve it one level @@ -1707,14 +1695,6 @@ ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) } } - - pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> { - let err = tcx.ty_error(); - TypeTrace { - cause: ObligationCause::dummy(), - values: Types(ExpectedFound { expected: err, found: err }), - } - } } impl<'tcx> SubregionOrigin<'tcx> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/nll_relate/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -157,7 +157,7 @@ fn create_scope( &mut self, - value: ty::Binder>, + value: ty::Binder<'tcx, impl Relate<'tcx>>, universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); @@ -279,7 +279,7 @@ /// Relate a type inference variable with a value type. This works /// by creating a "generalization" G of the value where all the /// lifetimes are replaced with fresh inference values. This - /// genearlization G becomes the value of the inference variable, + /// generalization G becomes the value of the inference variable, /// and is then related in turn to the value. So e.g. if you had /// `vid = ?0` and `value = &'a u32`, we might first instantiate /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable, @@ -608,9 +608,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -744,7 +744,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { self.target_index.shift_in(1); t.super_visit_with(self); @@ -997,9 +997,9 @@ fn binders( &mut self, - a: ty::Binder, - _: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + _: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/env.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/env.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/env.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/env.rs 2021-06-17 03:53:50.000000000 +0000 @@ -92,11 +92,6 @@ &self.region_bound_pairs_map } - /// Returns ownership of the `free_region_map`. - pub fn into_free_region_map(self) -> FreeRegionMap<'tcx> { - self.free_region_map - } - /// This is a hack to support the old-skool regionck, which /// processes region constraints from the main function and the /// closure together. In that context, when we enter a closure, we diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/outlives/obligations.rs 2021-06-17 03:53:50.000000000 +0000 @@ -186,28 +186,6 @@ } } } - - /// Processes a single ad-hoc region obligation that was not - /// registered in advance. - pub fn type_must_outlive( - &self, - region_bound_pairs: &RegionBoundPairs<'tcx>, - implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, - origin: infer::SubregionOrigin<'tcx>, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - ) { - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - region_bound_pairs, - implicit_region_bound, - param_env, - ); - let ty = self.resolve_vars_if_possible(ty); - outlives.type_must_outlive(origin, ty, region); - } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/region_constraints/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -309,31 +309,6 @@ any_unifications: bool, } -/// When working with placeholder regions, we often wish to find all of -/// the regions that are either reachable from a placeholder region, or -/// which can reach a placeholder region, or both. We call such regions -/// *tainted* regions. This struct allows you to decide what set of -/// tainted regions you want. -#[derive(Debug)] -pub struct TaintDirections { - incoming: bool, - outgoing: bool, -} - -impl TaintDirections { - pub fn incoming() -> Self { - TaintDirections { incoming: true, outgoing: false } - } - - pub fn outgoing() -> Self { - TaintDirections { incoming: false, outgoing: true } - } - - pub fn both() -> Self { - TaintDirections { incoming: true, outgoing: true } - } -} - impl<'tcx> RegionConstraintStorage<'tcx> { pub fn new() -> Self { Self::default() @@ -472,11 +447,6 @@ self.var_infos[vid].universe } - /// Returns the origin for the given variable. - pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_infos[vid].origin - } - fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) { // cannot add constraints once regions are resolved debug!("RegionConstraintCollector: add_constraint({:?})", constraint); @@ -795,16 +765,6 @@ VerifyBound::AnyBound(vec![self, vb]) } } - - pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> { - if self.must_hold() && vb.must_hold() { - self - } else if self.cannot_hold() && vb.cannot_hold() { - self - } else { - VerifyBound::AllBounds(vec![self, vb]) - } - } } impl<'tcx> RegionConstraintData<'tcx> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/resolve.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/resolve.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/resolve.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/resolve.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,6 @@ 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::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; @@ -46,6 +47,10 @@ ct.super_fold_with(self) } } + + fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + constant.super_fold_with(self) + } } /// The opportunistic region resolver opportunistically resolves regions diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/sub.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/sub.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/sub.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/sub.rs 2021-06-17 03:53:50.000000000 +0000 @@ -162,9 +162,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/type_variable.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/type_variable.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/type_variable.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/type_variable.rs 2021-06-17 03:53:50.000000000 +0000 @@ -146,9 +146,7 @@ } } -pub(crate) struct Instantiate { - vid: ty::TyVid, -} +pub(crate) struct Instantiate; pub(crate) struct Delegate; @@ -224,7 +222,7 @@ // Hack: we only need this so that `types_escaping_snapshot` // can see what has been unified; see the Delegate impl for // more details. - self.undo_log.push(Instantiate { vid }); + self.undo_log.push(Instantiate); } /// Creates a new type variable. @@ -346,56 +344,6 @@ ) } - /// Finds the set of type variables that existed *before* `s` - /// but which have only been unified since `s` started, and - /// return the types with which they were unified. So if we had - /// a type variable `V0`, then we started the snapshot, then we - /// created a type variable `V1`, unified `V0` with `T0`, and - /// unified `V1` with `T1`, this function would return `{T0}`. - pub fn types_escaping_snapshot(&mut self, s: &super::Snapshot<'tcx>) -> Vec> { - let mut new_elem_threshold = u32::MAX; - let mut escaping_types = Vec::new(); - let actions_since_snapshot = self.undo_log.actions_since_snapshot(s); - debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len()); - for i in 0..actions_since_snapshot.len() { - let actions_since_snapshot = self.undo_log.actions_since_snapshot(s); - match actions_since_snapshot[i] { - super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::NewElem(index))) => { - // if any new variables were created during the - // snapshot, remember the lower index (which will - // always be the first one we see). Note that this - // action must precede those variables being - // specified. - new_elem_threshold = cmp::min(new_elem_threshold, index as u32); - debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold); - } - - super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::Other( - Instantiate { vid, .. }, - ))) => { - if vid.index < new_elem_threshold { - // quick check to see if this variable was - // created since the snapshot started or not. - let mut eq_relations = ut::UnificationTable::with_log( - &mut self.storage.eq_relations, - &mut *self.undo_log, - ); - let escaping_type = match eq_relations.probe_value(vid) { - TypeVariableValue::Unknown { .. } => bug!(), - TypeVariableValue::Known { value } => value, - }; - escaping_types.push(escaping_type); - } - debug!("SpecifyVar({:?}) new_elem_threshold={}", vid, new_elem_threshold); - } - - _ => {} - } - } - - escaping_types - } - /// Returns indices of all variables that are not yet /// instantiated. pub fn unsolved_variables(&mut self) -> Vec { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/undo_log.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/undo_log.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/infer/undo_log.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/infer/undo_log.rs 2021-06-17 03:53:50.000000000 +0000 @@ -165,10 +165,6 @@ } impl<'tcx> InferCtxtUndoLogs<'tcx> { - pub fn actions_since_snapshot(&self, snapshot: &Snapshot<'tcx>) -> &[UndoLog<'tcx>] { - &self.logs[snapshot.undo_len..] - } - pub fn start_snapshot(&mut self) -> Snapshot<'tcx> { self.num_open_snapshots += 1; Snapshot { undo_len: self.logs.len(), _marker: PhantomData } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,7 +2,7 @@ //! //! - **Type inference.** The type inference code can be found in the `infer` module; //! this code handles low-level equality and subtyping operations. The -//! type check pass in the compiler is found in the `librustc_typeck` crate. +//! type check pass in the compiler is found in the `rustc_typeck` crate. //! //! For more information about how rustc works, see the [rustc dev guide]. //! @@ -16,11 +16,11 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(never_type)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(in_band_lifetimes)] #![feature(control_flow_enum)] #![recursion_limit = "512"] // For rustdoc diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/error_reporting/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -9,6 +9,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use std::fmt; +use std::iter; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_extra_impl_obligation( @@ -94,7 +95,7 @@ note_span .push_span_label(trait_span, "this trait cannot be made into an object...".to_string()); } - for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) { + for (span, msg) in iter::zip(multi_span, messages) { note_span.push_span_label(span, msg); } err.span_note( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -128,7 +128,7 @@ } impl<'tcx> TraitObligation<'tcx> { - pub fn self_ty(&self) -> ty::Binder> { + pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.predicate.map_bound(|p| p.self_ty()) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_infer/src/traits/util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_infer/src/traits/util.rs 2021-06-17 03:53:50.000000000 +0000 @@ -305,9 +305,7 @@ Some(assoc_name), )); for (super_predicate, _) in super_predicates.predicates { - let bound_predicate = super_predicate.kind(); - let subst_predicate = super_predicate - .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder())); + 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); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -45,7 +45,7 @@ rustc_resolve = { path = "../rustc_resolve" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tempfile = "3.0.5" +tempfile = "3.2" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["libloaderapi"] } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/callbacks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/callbacks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/callbacks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/callbacks.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ //! Throughout the compiler tree, there are several places which want to have //! access to state or queries while being inside crates that are dependencies -//! of librustc_middle. To facilitate this, we have the +//! of `rustc_middle`. To facilitate this, we have the //! `rustc_data_structures::AtomicRef` type, which allows us to setup a global //! static which can then be set in this file at program startup. //! @@ -13,8 +13,8 @@ use rustc_middle::ty::tls; use std::fmt; -/// This is a callback from librustc_ast as it cannot access the implicit state -/// in librustc_middle otherwise. +/// This is a callback from `rustc_ast` as it cannot access the implicit state +/// in `rustc_middle` otherwise. fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { tls::with_opt(|tcx| { if let Some(tcx) = tcx { @@ -25,8 +25,8 @@ }) } -/// This is a callback from librustc_ast as it cannot access the implicit state -/// in librustc_middle otherwise. It is used to when diagnostic messages are +/// This is a callback from `rustc_ast` as it cannot access the implicit state +/// in `rustc_middle` otherwise. It is used to when diagnostic messages are /// emitted and stores them in the current query, if there is one. fn track_diagnostic(diagnostic: &Diagnostic) { tls::with_context_opt(|icx| { @@ -39,8 +39,8 @@ }) } -/// This is a callback from librustc_hir as it cannot access the implicit state -/// in librustc_middle otherwise. +/// This is a callback from `rustc_hir` as it cannot access the implicit state +/// in `rustc_middle` otherwise. fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "DefId({}:{}", def_id.krate, def_id.index.index())?; tls::with_opt(|opt_tcx| { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/passes.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/passes.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/passes.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/passes.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,8 +15,8 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::Crate; -use rustc_index::vec::IndexVec; use rustc_lint::LintStore; +use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; @@ -788,13 +788,7 @@ callback(sess, &mut local_providers, &mut extern_providers); } - let queries = { - let crates = resolver_outputs.cstore.crates_untracked(); - let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); - let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); - providers[LOCAL_CRATE] = local_providers; - queries.get_or_init(|| TcxQueries::new(providers, extern_providers)) - }; + let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers)); let gcx = sess.time("setup_global_ctxt", || { global_ctxt.get_or_init(|| { @@ -838,6 +832,12 @@ }); sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); + + let cstore = tcx + .cstore_as_any() + .downcast_ref::() + .expect("`tcx.cstore` is not a `CStore`"); + cstore.report_unused_deps(tcx); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { @@ -1028,9 +1028,6 @@ rustc_symbol_mangling::test::report_symbol_names(tcx); } - tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx)); - tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx)); - info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/queries.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/queries.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/queries.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/queries.rs 2021-06-17 03:53:50.000000000 +0000 @@ -207,7 +207,13 @@ }) .open(self.session()) }); - DepGraph::new(prev_graph, prev_work_products) + + rustc_incremental::build_dep_graph( + self.session(), + prev_graph, + prev_work_products, + ) + .unwrap_or_else(DepGraph::new_disabled) } }) }) @@ -301,7 +307,7 @@ _ => return, }; - let attrs = &*tcx.get_attrs(def_id.to_def_id()); + let attrs = &*tcx.get_attrs(def_id); let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error)); for attr in attrs { match attr.meta_item_list() { @@ -435,6 +441,9 @@ if self.session().opts.debugging_opts.query_stats { gcx.enter(rustc_query_impl::print_stats); } + + self.session() + .time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); } _timer = Some(self.session().timer("free_global_ctxt")); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/tests.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; +use rustc_session::config::InstrumentCoverage; use rustc_session::config::Strip; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{ - Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel, + Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -17,7 +18,8 @@ use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; + use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::num::NonZeroUsize; @@ -73,6 +75,27 @@ BTreeMap::from_iter(entries.into_iter()) } +fn assert_same_clone(x: &Options) { + assert_eq!(x.dep_tracking_hash(true), x.clone().dep_tracking_hash(true)); + assert_eq!(x.dep_tracking_hash(false), x.clone().dep_tracking_hash(false)); +} + +fn assert_same_hash(x: &Options, y: &Options) { + assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true)); + assert_eq!(x.dep_tracking_hash(false), y.dep_tracking_hash(false)); + // Check clone + assert_same_clone(x); + assert_same_clone(y); +} + +fn assert_different_hash(x: &Options, y: &Options) { + assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true)); + assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false)); + // Check clone + assert_same_clone(x); + assert_same_clone(y); +} + // When the user supplies --test we should implicitly supply --cfg test #[test] fn test_switch_implies_cfg_test() { @@ -129,14 +152,9 @@ v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]); v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v2, &v3); } #[test] @@ -154,10 +172,7 @@ (OutputType::Exe, Some(PathBuf::from("./some/thing"))), ]); - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); } #[test] @@ -181,14 +196,9 @@ (String::from("d"), new_public_extern_entry(vec!["f", "e"])), ])); - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v2, &v3); } #[test] @@ -218,14 +228,9 @@ (String::from("d"), Level::Deny), ]; - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v2, &v3); } #[test] @@ -247,11 +252,7 @@ (String::from("d"), Level::Forbid), ]; - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); } #[test] @@ -291,15 +292,9 @@ v4.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v1, &v4); } #[test] @@ -337,15 +332,9 @@ (String::from("c"), None, NativeLibKind::Unspecified), ]; - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v1, &v4); } #[test] @@ -373,14 +362,9 @@ (String::from("b"), None, NativeLibKind::Framework), ]; - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v2, &v3); } #[test] @@ -390,8 +374,9 @@ macro_rules! untracked { ($name: ident, $non_default_value: expr) => { + assert_ne!(opts.cg.$name, $non_default_value); opts.cg.$name = $non_default_value; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_same_hash(&reference, &opts); }; } @@ -404,7 +389,6 @@ untracked!(incremental, Some(String::from("abc"))); // `link_arg` is omitted because it just forwards to `link_args`. untracked!(link_args, vec![String::from("abc"), String::from("def")]); - untracked!(link_dead_code, Some(true)); untracked!(link_self_contained, Some(true)); untracked!(linker, Some(PathBuf::from("linker"))); untracked!(linker_flavor, Some(LinkerFlavor::Gcc)); @@ -416,8 +400,9 @@ macro_rules! tracked { ($name: ident, $non_default_value: expr) => { opts = reference.clone(); + assert_ne!(opts.cg.$name, $non_default_value); opts.cg.$name = $non_default_value; - assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_different_hash(&reference, &opts); }; } @@ -432,6 +417,7 @@ tracked!(force_unwind_tables, Some(true)); tracked!(inline_threshold, Some(0xf007ba11)); tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto); + tracked!(link_dead_code, Some(true)); tracked!(llvm_args, vec![String::from("1"), String::from("2")]); tracked!(lto, LtoCli::Fat); tracked!(metadata, vec![String::from("A"), String::from("B")]); @@ -454,14 +440,41 @@ } #[test] +fn test_top_level_options_tracked_no_crate() { + let reference = Options::default(); + let mut opts; + + macro_rules! tracked { + ($name: ident, $non_default_value: expr) => { + opts = reference.clone(); + assert_ne!(opts.$name, $non_default_value); + opts.$name = $non_default_value; + // The crate hash should be the same + assert_eq!(reference.dep_tracking_hash(true), opts.dep_tracking_hash(true)); + // The incremental hash should be different + assert_ne!(reference.dep_tracking_hash(false), opts.dep_tracking_hash(false)); + }; + } + + // Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash. + // This list is in alphabetical order. + tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]); + tracked!( + real_rust_source_base_dir, + Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into()) + ); +} + +#[test] fn test_debugging_options_tracking_hash() { let reference = Options::default(); let mut opts = Options::default(); macro_rules! untracked { ($name: ident, $non_default_value: expr) => { + assert_ne!(opts.debugging_opts.$name, $non_default_value); opts.debugging_opts.$name = $non_default_value; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_same_hash(&reference, &opts); }; } @@ -470,8 +483,7 @@ untracked!(ast_json, true); untracked!(ast_json_noexpand, true); untracked!(borrowck, String::from("other")); - untracked!(borrowck_stats, true); - untracked!(deduplicate_diagnostics, true); + untracked!(deduplicate_diagnostics, false); untracked!(dep_tasks, true); untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); @@ -515,7 +527,7 @@ untracked!(self_profile_events, Some(vec![String::new()])); untracked!(span_debug, true); untracked!(span_free_formats, true); - untracked!(strip, Strip::None); + untracked!(strip, Strip::Debuginfo); untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); @@ -532,8 +544,9 @@ macro_rules! tracked { ($name: ident, $non_default_value: expr) => { opts = reference.clone(); + assert_ne!(opts.debugging_opts.$name, $non_default_value); opts.debugging_opts.$name = $non_default_value; - assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_different_hash(&reference, &opts); }; } @@ -560,13 +573,13 @@ tracked!(inline_mir, Some(true)); tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); - tracked!(instrument_coverage, true); + tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); - tracked!(mutable_noalias, true); + tracked!(mutable_noalias, Some(true)); tracked!(new_llvm_pass_manager, true); tracked!(no_codegen, true); tracked!(no_generate_arange_section, true); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_interface/src/util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_interface/src/util.rs 2021-06-17 03:53:50.000000000 +0000 @@ -265,7 +265,7 @@ let backend = match codegen_name { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), - codegen_name => get_builtin_codegen_backend(codegen_name), + codegen_name => get_builtin_codegen_backend(&sopts.maybe_sysroot, codegen_name), }; unsafe { @@ -390,15 +390,21 @@ } } -pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box { +pub fn get_builtin_codegen_backend( + maybe_sysroot: &Option, + backend_name: &str, +) -> fn() -> Box { match backend_name { #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - _ => get_codegen_sysroot(backend_name), + _ => get_codegen_sysroot(maybe_sysroot, backend_name), } } -pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box { +pub fn get_codegen_sysroot( + maybe_sysroot: &Option, + backend_name: &str, +) -> fn() -> Box { // 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`, @@ -413,8 +419,9 @@ let target = session::config::host_triple(); let sysroot_candidates = sysroot_candidates(); - let sysroot = sysroot_candidates + let sysroot = maybe_sysroot .iter() + .chain(sysroot_candidates.iter()) .map(|sysroot| { let libdir = filesearch::relative_target_lib_path(&sysroot, &target); sysroot.join(libdir).with_file_name("codegen-backends") @@ -450,8 +457,10 @@ let mut file: Option = None; - let expected_name = - format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")); + let expected_names = &[ + format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")), + format!("rustc_codegen_{}", backend_name), + ]; for entry in d.filter_map(|e| e.ok()) { let path = entry.path(); let filename = match path.file_name().and_then(|s| s.to_str()) { @@ -462,7 +471,7 @@ continue; } let name = &filename[DLL_PREFIX.len()..filename.len() - DLL_SUFFIX.len()]; - if name != expected_name { + if !expected_names.iter().any(|expected| expected == name) { continue; } if let Some(ref prev) = file { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lexer/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lexer/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lexer/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lexer/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,13 +1,13 @@ //! Low-level Rust lexer. //! -//! The idea with `librustc_lexer` is to make a reusable library, +//! The idea with `rustc_lexer` is to make a reusable library, //! by separating out pure lexing and rustc-specific concerns, like spans, //! error reporting, and interning. So, rustc_lexer operates directly on `&str`, //! produces simple tokens which are a pair of type-tag and a bit of original text, //! and does not report errors, instead storing them as flags on the token. //! //! Tokens produced by this lexer are not yet ready for parsing the Rust syntax. -//! For that see [`librustc_parse::lexer`], which converts this basic token stream +//! For that see [`rustc_parse::lexer`], which converts this basic token stream //! into wide tokens used by actual parser. //! //! The purpose of this crate is to convert raw sources into a labeled sequence @@ -17,7 +17,7 @@ //! The main entity of this crate is the [`TokenKind`] enum which represents common //! lexeme types. //! -//! [`librustc_parse::lexer`]: ../rustc_parse/lexer/index.html +//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html // We want to be able to build this crate with a stable compiler, so no // `#![feature]` attributes should be added. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/builtin.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/builtin.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/builtin.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/builtin.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + //! Lints in the Rust compiler. //! //! This contains lints which can feasibly be implemented as their own @@ -481,7 +483,7 @@ return false; } - if attr.is_value_str() { + if attr.value_str().is_some() { return true; } @@ -565,7 +567,7 @@ } fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.span, "the", "crate"); + self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate"); for macro_def in krate.exported_macros { let attrs = cx.tcx.hir().attrs(macro_def.hir_id()); @@ -857,11 +859,10 @@ /// ``` /// /// This syntax is now a hard error in the 2018 edition. In the 2015 - /// edition, this lint is "allow" by default, because the old code is - /// still valid, and warning for all old code can be noisy. This lint + /// edition, this lint is "warn" by default. This lint /// enables the [`cargo fix`] tool with the `--edition` flag to /// automatically transition old code from the 2015 edition to 2018. The - /// tool will switch this lint to "warn" and will automatically apply the + /// tool will run this lint and automatically apply the /// suggested fix from the compiler (which is to add `_` to each /// parameter). This provides a completely automated way to update old /// code for a new edition. See [issue #41686] for more details. @@ -869,7 +870,7 @@ /// [issue #41686]: https://github.com/rust-lang/rust/issues/41686 /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html pub ANONYMOUS_PARAMETERS, - Allow, + Warn, "detects anonymous parameters", @future_incompatible = FutureIncompatibleInfo { reference: "issue #41686 ", @@ -884,6 +885,10 @@ impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { + if cx.sess.edition() != Edition::Edition2015 { + // This is a hard error in future editions; avoid linting and erroring + return; + } if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind { for arg in sig.decl.inputs.iter() { if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { @@ -989,7 +994,7 @@ Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi()))); } - if attrs.peek().map(|next_attr| next_attr.is_doc_comment()).unwrap_or_default() { + if attrs.peek().map_or(false, |next_attr| next_attr.is_doc_comment()) { continue; } @@ -2280,7 +2285,7 @@ } declare_lint_pass!( - /// Check for used feature gates in `INCOMPLETE_FEATURES` in `librustc_feature/active.rs`. + /// Check for used feature gates in `INCOMPLETE_FEATURES` in `rustc_feature/src/active.rs`. IncompleteFeatures => [INCOMPLETE_FEATURES] ); @@ -2959,5 +2964,90 @@ } } } + } +} + +declare_lint! { + /// The `deref_nullptr` lint detects when an null pointer is dereferenced, + /// which causes [undefined behavior]. + /// + /// ### Example + /// + /// ```rust,no_run + /// # #![allow(unused)] + /// use std::ptr; + /// unsafe { + /// let x = &*ptr::null::(); + /// let x = ptr::addr_of!(*ptr::null::()); + /// let x = *(0 as *const i32); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Dereferencing a null pointer causes [undefined behavior] even as a place expression, + /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + pub DEREF_NULLPTR, + Warn, + "detects when an null pointer is dereferenced" +} + +declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]); + +impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { + /// test if expression is a null ptr + fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Cast(ref expr, ref ty) => { + if let rustc_hir::TyKind::Ptr(_) = ty.kind { + return is_zero(expr) || is_null_ptr(cx, expr); + } + } + // check for call to `core::ptr::null` or `core::ptr::null_mut` + rustc_hir::ExprKind::Call(ref path, _) => { + if let rustc_hir::ExprKind::Path(ref qpath) = path.kind { + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() { + return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id) + || cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id); + } + } + } + _ => {} + } + false + } + + /// test if expression is the literal `0` + fn is_zero(expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Lit(ref lit) => { + if let LitKind::Int(a, _) = lit.node { + return a == 0; + } + } + _ => {} + } + false + } + + if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind { + if let rustc_hir::UnOp::Deref = un_op { + if is_null_ptr(cx, expr_deref) { + cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { + let mut err = lint.build("dereferencing a null pointer"); + err.span_label( + expr.span, + "this code causes undefined behavior when executed", + ); + err.emit(); + }); + } + } + } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/context.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/context.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/context.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/context.rs 2021-06-17 03:53:50.000000000 +0000 @@ -45,6 +45,7 @@ use tracing::debug; use std::cell::Cell; +use std::iter; use std::slice; /// Information about the registered lints. @@ -176,6 +177,7 @@ self.early_passes.push(Box::new(pass)); } + /// Used by clippy. pub fn register_pre_expansion_pass( &mut self, pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, @@ -707,6 +709,9 @@ BuiltinLintDiagnostics::ProcMacroBackCompat(note) => { db.note(¬e); } + BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => { + db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); @@ -861,10 +866,12 @@ /// // The given `def_id` is that of an `Option` type /// } /// ``` + /// + /// Used by clippy, but should be replaced by diagnostic items eventually. pub fn match_def_path(&self, def_id: DefId, path: &[Symbol]) -> bool { let names = self.get_def_path(def_id); - names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| a == b) + names.len() == path.len() && iter::zip(names, path).all(|(a, &b)| a == b) } /// Gets the absolute path of `def_id` as a vector of `Symbol`. @@ -905,7 +912,7 @@ fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Ok(()) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/early.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/early.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/early.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/early.rs 2021-06-17 03:53:50.000000000 +0000 @@ -109,6 +109,7 @@ fn visit_anon_const(&mut self, c: &'a ast::AnonConst) { run_early_pass!(self, check_anon_const, c); + self.check_id(c.id); ast_visit::walk_anon_const(self, c); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/levels.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/levels.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/levels.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/levels.rs 2021-06-17 03:53:50.000000000 +0000 @@ -236,10 +236,9 @@ Some(lvl) => lvl, }; - let meta = unwrap_or!(attr.meta(), continue); self.sess.mark_attr_used(attr); - let mut metas = unwrap_or!(meta.meta_item_list(), continue); + let mut metas = unwrap_or!(attr.meta_item_list(), continue); if metas.is_empty() { // FIXME (#55112): issue unused-attributes lint for `#[level()]` @@ -255,8 +254,6 @@ ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { if item.path == sym::reason { - // found reason, reslice meta list to exclude it - metas = &metas[0..metas.len() - 1]; // FIXME (#55112): issue unused-attributes lint if we thereby // don't have any lint names (`#[level(reason = "foo")]`) if let ast::LitKind::Str(rationale, _) = name_value.kind { @@ -275,6 +272,8 @@ .span_label(name_value.span, "reason must be a string literal") .emit(); } + // found reason, reslice meta list to exclude it + metas.pop().unwrap(); } else { bad_attr(item.span) .span_label(item.span, "bad attribute argument") @@ -288,10 +287,10 @@ } for li in metas { - let meta_item = match li.meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item, + let sp = li.span(); + let mut meta_item = match li { + ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item, _ => { - let sp = li.span(); let mut err = bad_attr(sp); let mut add_label = true; if let Some(item) = li.meta_item() { @@ -330,15 +329,19 @@ continue; } - Some(tool_ident.name) + Some(meta_item.path.segments.remove(0).ident.name) } else { None }; - let name = meta_item.path.segments.last().expect("empty lint name").ident.name; - let lint_result = store.check_lint_name(&name.as_str(), tool_name); + let name = pprust::path_to_string(&meta_item.path); + let lint_result = store.check_lint_name(&name, tool_name); match &lint_result { CheckLintNameResult::Ok(ids) => { - let src = LintLevelSource::Node(name, li.span(), reason); + let src = LintLevelSource::Node( + meta_item.path.segments.last().expect("empty lint name").ident.name, + sp, + reason, + ); for &id in *ids { self.check_gated_lint(id, attr.span); self.insert_spec(&mut specs, id, (level, src)); @@ -351,7 +354,7 @@ let complete_name = &format!("{}::{}", tool_name.unwrap(), name); let src = LintLevelSource::Node( Symbol::intern(complete_name), - li.span(), + sp, reason, ); for id in ids { @@ -367,7 +370,7 @@ lint, lvl, src, - Some(li.span().into()), + Some(sp.into()), |lint| { let msg = format!( "lint name `{}` is deprecated \ @@ -376,7 +379,7 @@ ); lint.build(&msg) .span_suggestion( - li.span(), + sp, "change it to", new_lint_name.to_string(), Applicability::MachineApplicable, @@ -387,7 +390,7 @@ let src = LintLevelSource::Node( Symbol::intern(&new_lint_name), - li.span(), + sp, reason, ); for id in ids { @@ -414,12 +417,12 @@ lint, renamed_lint_level, src, - Some(li.span().into()), + Some(sp.into()), |lint| { let mut err = lint.build(&msg); if let Some(new_name) = &renamed { err.span_suggestion( - li.span(), + sp, "use the new name", new_name.to_string(), Applicability::MachineApplicable, @@ -433,30 +436,23 @@ let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); - struct_lint_level( - self.sess, - lint, - level, - src, - Some(li.span().into()), - |lint| { - let name = if let Some(tool_name) = tool_name { - format!("{}::{}", tool_name, name) - } else { - name.to_string() - }; - let mut db = lint.build(&format!("unknown lint: `{}`", name)); - if let Some(suggestion) = suggestion { - db.span_suggestion( - li.span(), - "did you mean", - suggestion.to_string(), - Applicability::MachineApplicable, - ); - } - db.emit(); - }, - ); + struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| { + let name = if let Some(tool_name) = tool_name { + format!("{}::{}", tool_name, name) + } else { + name.to_string() + }; + let mut db = lint.build(&format!("unknown lint: `{}`", name)); + if let Some(suggestion) = suggestion { + db.span_suggestion( + sp, + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); + } + db.emit(); + }); } } // If this lint was renamed, apply the new lint instead of ignoring the attribute. @@ -464,15 +460,15 @@ // we don't warn about the name change. if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate - if let CheckLintNameResult::Ok(ids) = - store.check_lint_name(&new_name, tool_name) - { - let src = - LintLevelSource::Node(Symbol::intern(&new_name), li.span(), reason); + // NOTE: `new_name` already includes the tool name, so we don't have to add it again. + if let CheckLintNameResult::Ok(ids) = store.check_lint_name(&new_name, None) { + let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason); for &id in ids { self.check_gated_lint(id, attr.span); self.insert_spec(&mut specs, id, (level, src)); } + } else { + panic!("renamed lint does not exist: {}", new_name); } } } @@ -564,10 +560,6 @@ self.id_to_set.insert(id, self.cur); } - pub fn build(self) -> LintLevelSets { - self.sets - } - pub fn build_map(self) -> LintLevelMap { LintLevelMap { sets: self.sets, id_to_set: self.id_to_set } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -33,9 +33,10 @@ #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(iter_order_by)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] @@ -205,6 +206,7 @@ UnreachablePub: UnreachablePub, ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, InvalidValue: InvalidValue, + DerefNullPtr: DerefNullPtr, ] ); }; @@ -325,6 +327,7 @@ store.register_renamed("exceeding_bitshifts", "arithmetic_overflow"); store.register_renamed("redundant_semicolon", "redundant_semicolons"); store.register_renamed("overlapping_patterns", "overlapping_range_endpoints"); + store.register_renamed("safe_packed_borrows", "unaligned_references"); // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/non_ascii_idents.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/non_ascii_idents.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/non_ascii_idents.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/non_ascii_idents.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,7 +10,6 @@ /// /// ```rust,compile_fail /// # #![allow(unused)] - /// #![feature(non_ascii_idents)] /// #![deny(non_ascii_idents)] /// fn main() { /// let föö = 1; @@ -21,14 +20,11 @@ /// /// ### Explanation /// - /// Currently on stable Rust, identifiers must contain ASCII characters. - /// The [`non_ascii_idents`] nightly-only feature allows identifiers to - /// contain non-ASCII characters. This lint allows projects that wish to - /// retain the limit of only using ASCII characters to switch this lint to - /// "forbid" (for example to ease collaboration or for security reasons). + /// This lint allows projects that wish to retain the limit of only using + /// ASCII characters to switch this lint to "forbid" (for example to ease + /// collaboration or for security reasons). /// See [RFC 2457] for more details. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [RFC 2457]: https://github.com/rust-lang/rfcs/blob/master/text/2457-non-ascii-idents.md pub NON_ASCII_IDENTS, Allow, @@ -44,7 +40,6 @@ /// /// ```rust /// # #![allow(unused)] - /// #![feature(non_ascii_idents)] /// const µ: f64 = 0.000001; /// ``` /// @@ -52,10 +47,8 @@ /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// about using characters which are not commonly used, and may cause - /// visual confusion. + /// This lint warns about using characters which are not commonly used, and may + /// cause visual confusion. /// /// This lint is triggered by identifiers that contain a codepoint that is /// not part of the set of "Allowed" codepoints as described by [Unicode® @@ -66,7 +59,6 @@ /// that if you "forbid" this lint that existing code may fail in the /// future. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [TR39Allowed]: https://www.unicode.org/reports/tr39/#General_Security_Profile pub UNCOMMON_CODEPOINTS, Warn, @@ -81,8 +73,6 @@ /// ### Example /// /// ```rust - /// #![feature(non_ascii_idents)] - /// /// // Latin Capital Letter E With Caron /// pub const Ě: i32 = 1; /// // Latin Capital Letter E With Breve @@ -93,10 +83,8 @@ /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// when different identifiers may appear visually similar, which can - /// cause confusion. + /// This lint warns when different identifiers may appear visually similar, + /// which can cause confusion. /// /// The confusable detection algorithm is based on [Unicode® Technical /// Standard #39 Unicode Security Mechanisms Section 4 Confusable @@ -110,7 +98,6 @@ /// Beware that if you "forbid" this lint that existing code may fail in /// the future. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [TR39Confusable]: https://www.unicode.org/reports/tr39/#Confusable_Detection pub CONFUSABLE_IDENTS, Warn, @@ -127,8 +114,6 @@ /// ### Example /// /// ```rust - /// #![feature(non_ascii_idents)] - /// /// // The Japanese katakana character エ can be confused with the Han character 工. /// const エ: &'static str = "アイウ"; /// ``` @@ -137,10 +122,8 @@ /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// when characters between different scripts may appear visually similar, - /// which can cause confusion. + /// This lint warns when characters between different scripts may appear + /// visually similar, which can cause confusion. /// /// If the crate contains other identifiers in the same script that have /// non-confusable characters, then this lint will *not* be issued. For @@ -152,8 +135,6 @@ /// Note that the set of confusable characters may change over time. /// Beware that if you "forbid" this lint that existing code may fail in /// the future. - /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html pub MIXED_SCRIPT_CONFUSABLES, Warn, "detects Unicode scripts whose mixed script confusables codepoints are solely used", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/types.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/types.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint/src/types.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint/src/types.rs 2021-06-17 03:53:50.000000000 +0000 @@ -17,6 +17,7 @@ use rustc_target::spec::abi::Abi as SpecAbi; use std::cmp; +use std::iter; use std::ops::ControlFlow; use tracing::debug; @@ -1255,7 +1256,7 @@ let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(sig); - for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) { + for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false); } @@ -1355,10 +1356,7 @@ layout ); - let (largest, slargest, largest_index) = enum_definition - .variants - .iter() - .zip(variants) + let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants) .map(|(variant, variant_layout)| { // Subtract the size of the enum tag. let bytes = variant_layout.size.bytes().saturating_sub(tag_size); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint_defs/src/builtin.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint_defs/src/builtin.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint_defs/src/builtin.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint_defs/src/builtin.rs 2021-06-17 03:53:50.000000000 +0000 @@ -547,7 +547,7 @@ /// Also consider if you intended to use an _inner attribute_ (with a `!` /// such as `#![allow(unused)]`) which applies to the item the attribute /// is within, or an _outer attribute_ (without a `!` such as - /// `#[allow(unsued)]`) which applies to the item *following* the + /// `#[allow(unused)]`) which applies to the item *following* the /// attribute. /// /// [attributes]: https://doc.rust-lang.org/reference/attributes.html @@ -1057,6 +1057,7 @@ /// unsafe { /// let foo = Foo { field1: 0, field2: 0 }; /// let _ = &foo.field1; + /// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint. /// } /// } /// ``` @@ -1065,20 +1066,20 @@ /// /// ### Explanation /// - /// Creating a reference to an insufficiently aligned packed field is - /// [undefined behavior] and should be disallowed. - /// - /// This lint is "allow" by default because there is no stable - /// alternative, and it is not yet certain how widespread existing code - /// will trigger this lint. - /// - /// See [issue #27060] for more discussion. + /// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and + /// should be disallowed. Using an `unsafe` block does not change anything about this. Instead, + /// the code should do a copy of the data in the packed field or use raw pointers and unaligned + /// accesses. See [issue #82523] for more information. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// [issue #27060]: https://github.com/rust-lang/rust/issues/27060 + /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523 pub UNALIGNED_REFERENCES, - Allow, + Warn, "detects unaligned references to fields of packed structs", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #82523 ", + edition: None, + }; report_in_external_macro } @@ -1151,49 +1152,6 @@ } declare_lint! { - /// The `safe_packed_borrows` lint detects borrowing a field in the - /// interior of a packed structure with alignment other than 1. - /// - /// ### Example - /// - /// ```rust - /// #[repr(packed)] - /// pub struct Unaligned(pub T); - /// - /// pub struct Foo { - /// start: u8, - /// data: Unaligned, - /// } - /// - /// fn main() { - /// let x = Foo { start: 0, data: Unaligned(1) }; - /// let y = &x.data.0; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// This type of borrow is unsafe and can cause errors on some platforms - /// and violates some assumptions made by the compiler. This was - /// previously allowed unintentionally. This is a [future-incompatible] - /// lint to transition this to a hard error in the future. See [issue - /// #46043] for more details, including guidance on how to solve the - /// problem. - /// - /// [issue #46043]: https://github.com/rust-lang/rust/issues/46043 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub SAFE_PACKED_BORROWS, - Warn, - "safe borrows of fields of packed structs were erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46043 ", - edition: None, - }; -} - -declare_lint! { /// The `patterns_in_fns_without_body` lint detects `mut` identifier /// patterns as a parameter in functions without a body. /// @@ -1977,7 +1935,7 @@ Warn, "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #50504 ", + reference: "issue #83583 ", edition: None, }; } @@ -2487,6 +2445,52 @@ } declare_lint! { + /// The `bad_asm_style` lint detects the use of the `.intel_syntax` and + /// `.att_syntax` directives. + /// + /// ### Example + /// + /// ```rust,ignore (fails on system llvm) + /// #![feature(asm)] + /// + /// fn main() { + /// #[cfg(target_arch="x86_64")] + /// unsafe { + /// asm!( + /// ".att_syntax", + /// "movl {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 + /// ``` + /// + /// ### Explanation + /// + /// On x86, `asm!` uses the intel assembly syntax by default. While this + /// can be switched using assembler directives like `.att_syntax`, using the + /// `att_syntax` option is recommended instead because it will also properly + /// prefix register placeholders with `%` as required by AT&T syntax. + pub BAD_ASM_STYLE, + Warn, + "incorrect use of inline assembly", +} + +declare_lint! { /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe /// functions without an explicit unsafe block. /// @@ -2518,9 +2522,10 @@ /// /// The fix to this is to wrap the unsafe code in an `unsafe` block. /// - /// This lint is "allow" by default because it has not yet been - /// stabilized, and is not yet complete. See [RFC #2585] and [issue - /// #71668] for more details + /// This lint is "allow" by default since this will affect a large amount + /// of existing code, and the exact plan for increasing the severity is + /// still being considered. See [RFC #2585] and [issue #71668] for more + /// details. /// /// [`unsafe fn`]: https://doc.rust-lang.org/reference/unsafe-functions.html /// [`unsafe` block]: https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks @@ -2673,7 +2678,7 @@ /// Statics with an uninhabited type can never be initialized, so they are impossible to define. /// However, this can be side-stepped with an `extern static`, leading to problems later in the /// compiler which assumes that there are no initialized uninhabited places (such as locals or - /// statics). This was accientally allowed, but is being phased out. + /// statics). This was accidentally allowed, but is being phased out. pub UNINHABITED_STATIC, Warn, "uninhabited static", @@ -2872,6 +2877,39 @@ }; } +declare_lint! { + /// The `large_assignments` lint detects when objects of large + /// types are being moved around. + /// + /// ### Example + /// + /// ```rust,ignore (can crash on some platforms) + /// let x = [0; 50000]; + /// let y = x; + /// ``` + /// + /// produces: + /// + /// ```text + /// warning: moving a large value + /// --> $DIR/move-large.rs:1:3 + /// let y = x; + /// - Copied large value here + /// ``` + /// + /// ### Explanation + /// + /// When using a large type in a plain assignment or in a function + /// argument, idiomatic code can be inefficient. + /// Ideally appropriate optimizations would resolve this, but such + /// optimizations are only done in a best-effort manner. + /// This lint will trigger on all sites of large moves and thus allow the + /// user to resolve them in code. + pub LARGE_ASSIGNMENTS, + Warn, + "detects large moves or copies", +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -2907,7 +2945,6 @@ RENAMED_AND_REMOVED_LINTS, UNALIGNED_REFERENCES, CONST_ITEM_MUTATION, - SAFE_PACKED_BORROWS, PATTERNS_IN_FNS_WITHOUT_BODY, MISSING_FRAGMENT_SPECIFIER, LATE_BOUND_LIFETIME_ARGUMENTS, @@ -2941,6 +2978,7 @@ NONTRIVIAL_STRUCTURAL_MATCH, SOFT_UNSTABLE, INLINE_NO_SANITIZE, + BAD_ASM_STYLE, ASM_SUB_REGISTER, UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, @@ -2956,6 +2994,8 @@ DISJOINT_CAPTURE_DROP_REORDER, LEGACY_DERIVE_HELPERS, PROC_MACRO_BACK_COMPAT, + OR_PATTERNS_BACK_COMPAT, + LARGE_ASSIGNMENTS, ] } @@ -3133,3 +3173,37 @@ }) }; } + +declare_lint! { + /// The `or_patterns_back_compat` lint detects usage of old versions of or-patterns. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(or_patterns_back_compat)] + /// macro_rules! match_any { + /// ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + /// match $expr { + /// $( + /// $( $pat => $expr_arm, )+ + /// )+ + /// } + /// }; + /// } + /// + /// fn main() { + /// let result: Result = Err(42); + /// let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + /// assert_eq!(int, 42); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In Rust 2021, the pat matcher will match new patterns, which include the | character. + pub OR_PATTERNS_BACK_COMPAT, + Allow, + "detects usage of old versions of or-patterns", +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint_defs/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint_defs/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_lint_defs/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_lint_defs/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -267,6 +267,7 @@ LegacyDeriveHelpers(Span), ExternDepSpec(String, ExternDepSpec), ProcMacroBackCompat(String), + OrPatternsBackCompat(Span, String), } /// Lints that are buffered up early on in the `Session` before the diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/build.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/build.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/build.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/build.rs 2021-06-17 03:53:50.000000000 +0000 @@ -88,16 +88,6 @@ "riscv", ]; - let mut version_cmd = Command::new(&llvm_config); - version_cmd.arg("--version"); - let version_output = output(&mut version_cmd); - let mut parts = version_output.split('.').take(2).filter_map(|s| s.parse::().ok()); - let (major, _minor) = if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { - (major, minor) - } else { - (8, 0) - }; - let required_components = &[ "ipo", "bitreader", @@ -123,10 +113,6 @@ println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); } - if major >= 9 { - println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser"); - } - // Link in our own LLVM shims, compiled with the same flags as LLVM let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp 2021-06-17 03:53:50.000000000 +0000 @@ -91,11 +91,7 @@ extern "C" LLVMRustArchiveIteratorRef LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) { Archive *Archive = RustArchive->getBinary(); -#if LLVM_VERSION_GE(10, 0) std::unique_ptr Err = std::make_unique(Error::success()); -#else - std::unique_ptr Err = llvm::make_unique(Error::success()); -#endif auto Cur = Archive->child_begin(*Err); if (*Err) { LLVMRustSetLastError(toString(std::move(*Err)).c_str()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp 2021-06-17 03:53:50.000000000 +0000 @@ -23,10 +23,17 @@ const char* const Filenames[], size_t FilenamesLen, RustStringRef BufferOut) { +#if LLVM_VERSION_GE(13,0) + SmallVector FilenameRefs; + for (size_t i = 0; i < FilenamesLen; i++) { + FilenameRefs.push_back(std::string(Filenames[i])); + } +#else SmallVector FilenameRefs; for (size_t i = 0; i < FilenamesLen; i++) { FilenameRefs.push_back(StringRef(Filenames[i])); } +#endif auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( makeArrayRef(FilenameRefs)); RawRustStringOstream OS(BufferOut); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h 2021-06-17 03:53:50.000000000 +0000 @@ -33,13 +33,6 @@ (LLVM_VERSION_MAJOR > (major) || \ LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor)) -#define LLVM_VERSION_EQ(major, minor) \ - (LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor)) - -#define LLVM_VERSION_LE(major, minor) \ - (LLVM_VERSION_MAJOR < (major) || \ - LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor)) - #define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor))) #include "llvm/IR/LegacyPassManager.h" diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp 2021-06-17 03:53:50.000000000 +0000 @@ -65,13 +65,9 @@ } extern "C" void LLVMTimeTraceProfilerInitialize() { -#if LLVM_VERSION_GE(10, 0) timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, /* ProcName */ "rustc"); -#else - timeTraceProfilerInitialize(); -#endif } extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { @@ -408,26 +404,21 @@ printf("\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { +extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const ArrayRef FeatTable = MCInfo->getFeatureTable(); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable); - - printf("Available features for this target:\n"); - for (auto &Feature : FeatTable) - printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("\nRust-specific features:\n"); - printf(" %-*s - %s.\n", - MaxFeatLen, - "crt-static", - "Enables libraries with C Run-time Libraries(CRT) to be statically linked" - ); - printf("\n"); + return FeatTable.size(); +} - printf("Use +feature to enable a feature, or -feature to disable it.\n" - "For example, rustc -C -target-cpu=mycpu -C " - "target-feature=+feature1,-feature2\n\n"); +extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, + const char** Feature, const char** Desc) { + const TargetMachine *Target = unwrap(TM); + const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); + const ArrayRef FeatTable = MCInfo->getFeatureTable(); + const SubtargetFeatureKV Feat = FeatTable[Index]; + *Feature = Feat.Key; + *Desc = Feat.Desc; } #else @@ -436,9 +427,11 @@ printf("Target CPU help is not supported by this LLVM version.\n\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { - printf("Target features help is not supported by this LLVM version.\n\n"); +extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) { + return 0; } + +extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {} #endif extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { @@ -596,7 +589,6 @@ ObjectFile, }; -#if LLVM_VERSION_GE(10, 0) static CodeGenFileType fromRust(LLVMRustFileType Type) { switch (Type) { case LLVMRustFileType::AssemblyFile: @@ -607,18 +599,6 @@ report_fatal_error("Bad FileType."); } } -#else -static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) { - switch (Type) { - case LLVMRustFileType::AssemblyFile: - return TargetMachine::CGFT_AssemblyFile; - case LLVMRustFileType::ObjectFile: - return TargetMachine::CGFT_ObjectFile; - default: - report_fatal_error("Bad FileType."); - } -} -#endif extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, @@ -868,13 +848,11 @@ } ); #else -#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(MemorySanitizerPass(Options)); } ); -#endif OptimizerLastEPCallbacks.push_back( [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(MemorySanitizerPass(Options)); @@ -892,13 +870,11 @@ } ); #else -#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(ThreadSanitizerPass()); } ); -#endif OptimizerLastEPCallbacks.push_back( [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(ThreadSanitizerPass()); @@ -989,13 +965,11 @@ MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); -# if LLVM_VERSION_GE(10, 0) if (PGOOpt) { PB.addPGOInstrPassesForO0( MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); } -# endif #endif } else { #if LLVM_VERSION_GE(12, 0) @@ -1366,11 +1340,7 @@ int num_modules, const char **preserved_symbols, int num_symbols) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { @@ -1437,9 +1407,17 @@ Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; +#if LLVM_VERSION_GE(13,0) + // Uses FromPrevailing visibility scheme which works for many binary + // formats. We probably could and should use ELF visibility scheme for many of + // our targets, however. + lto::Config conf; + thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage, + Ret->GUIDPreservedSymbols); +#else thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage, Ret->GUIDPreservedSymbols); - +#endif // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all // summaries in the index, and we basically just only want to ensure that dead @@ -1455,7 +1433,6 @@ ExportedGUIDs.insert(GUID); } } -#if LLVM_VERSION_GE(10, 0) auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); return (ExportList != Ret->ExportLists.end() && @@ -1463,15 +1440,6 @@ ExportedGUIDs.count(VI.getGUID()); }; thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); -#else - auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { - const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); - return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(GUID)) || - ExportedGUIDs.count(GUID); - }; - thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); -#endif return Ret.release(); } @@ -1628,11 +1596,7 @@ extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif { raw_string_ostream OS(Ret->data); { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp 2021-06-17 03:53:50.000000000 +0000 @@ -349,8 +349,10 @@ F->setAttributes(PALNew); } -// enable fpmath flag UnsafeAlgebra -extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { +// Enable a fast-math flag +// +// https://llvm.org/docs/LangRef.html#fast-math-flags +extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { if (auto I = dyn_cast(unwrap(V))) { I->setFast(true); } @@ -382,9 +384,18 @@ LLVMValueRef Old, LLVMValueRef Source, LLVMAtomicOrdering Order, LLVMAtomicOrdering FailureOrder, LLVMBool Weak) { +#if LLVM_VERSION_GE(13,0) + // Rust probably knows the alignment of the target value and should be able to + // specify something more precise than MaybeAlign here. See also + // https://reviews.llvm.org/D97224 which may be a useful reference. + AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( + unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order), + fromRust(FailureOrder)); +#else AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order), fromRust(FailureOrder)); +#endif ACXI->setWeak(Weak); return wrap(ACXI); } @@ -532,11 +543,6 @@ if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { Result |= DINode::DIFlags::FlagAppleBlock; } -#if LLVM_VERSION_LT(10, 0) - if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { - Result |= DINode::DIFlags::FlagBlockByrefStruct; - } -#endif if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { Result |= DINode::DIFlags::FlagVirtual; } @@ -901,9 +907,7 @@ unwrapDI(Context), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, -#if LLVM_VERSION_GE(10, 0) /* isDefined */ true, -#endif InitExpr, unwrapDIPtr(Decl), /* templateParams */ nullptr, AlignInBits); @@ -1090,19 +1094,11 @@ extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **Ptr) { -#if LLVM_VERSION_GE(10, 0) auto NameOrErr = (*unwrap(SI))->getName(); if (!NameOrErr) report_fatal_error(NameOrErr.takeError()); *Ptr = NameOrErr->data(); return NameOrErr->size(); -#else - StringRef Ret; - if (std::error_code EC = (*unwrap(SI))->getName(Ret)) - report_fatal_error(EC.message()); - *Ptr = Ret.data(); - return Ret.size(); -#endif } // LLVMArrayType function does not support 64-bit ElementCount @@ -1304,9 +1300,19 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) +#if LLVM_VERSION_LT(13, 0) +using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy; +#else +using LLVMInlineAsmDiagHandlerTy = void*; +#endif + extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( - LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { + LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) { + // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting + // with LLVM 13 this function is gone. +#if LLVM_VERSION_LT(13, 0) unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); +#endif } extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, @@ -1441,47 +1447,28 @@ LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemCpy( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemMove( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Val, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemSet( unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); -#endif } extern "C" LLVMValueRef @@ -1661,17 +1648,17 @@ LLVMSetVisibility(V, fromRust(RustVisibility)); } +extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) { + unwrap(Global)->setDSOLocal(is_dso_local); +} + struct LLVMRustModuleBuffer { std::string data; }; extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif { raw_string_ostream OS(Ret->data); { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_llvm/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_llvm/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -125,10 +125,7 @@ LLVMInitializeMSP430TargetInfo, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, - LLVMInitializeMSP430AsmPrinter - ); - init_target!( - all(llvm_component = "msp430", llvm_has_msp430_asm_parser), + LLVMInitializeMSP430AsmPrinter, LLVMInitializeMSP430AsmParser ); init_target!( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_macros/src/symbols/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_macros/src/symbols/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_macros/src/symbols/tests.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_macros/src/symbols/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -43,7 +43,7 @@ "Macro generated a different number of errors than expected" ); - for (found_error, &expected_error) in found_errors.iter().zip(expected_errors.iter()) { + for (found_error, &expected_error) in found_errors.iter().zip(expected_errors) { let found_error_str = format!("{}", found_error); assert_eq!(found_error_str, expected_error); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/Cargo.toml 2021-06-17 03:53:50.000000000 +0000 @@ -11,7 +11,6 @@ libc = "0.2" snap = "1" tracing = "0.1" -memmap2 = "0.2.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/creader.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/creader.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/creader.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/creader.rs 2021-06-17 03:53:50.000000000 +0000 @@ -46,6 +46,9 @@ /// This map is used to verify we get no hash conflicts between /// `StableCrateId` values. stable_crate_ids: FxHashMap, + + /// Unused externs of the crate + unused_externs: Vec, } pub struct CrateLoader<'a> { @@ -190,6 +193,27 @@ crate fn has_global_allocator(&self) -> bool { self.has_global_allocator } + + pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) { + // We put the check for the option before the lint_level_at_node call + // because the call mutates internal state and introducing it + // leads to some ui tests failing. + if !tcx.sess.opts.json_unused_externs { + return; + } + let level = tcx + .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID) + .0; + if level != lint::Level::Allow { + let unused_externs = + self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::>(); + let unused_externs = unused_externs.iter().map(String::as_str).collect::>(); + tcx.sess + .parse_sess + .span_diagnostic + .emit_unused_externs(level.as_str(), &unused_externs); + } + } } impl<'a> CrateLoader<'a> { @@ -217,6 +241,7 @@ allocator_kind: None, has_global_allocator: false, stable_crate_ids, + unused_externs: Vec::new(), }, used_extern_options: Default::default(), } @@ -350,7 +375,6 @@ let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - self.verify_no_symbol_conflicts(&crate_root)?; let private_dep = self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep); @@ -358,8 +382,6 @@ // Claim this crate number and cache it let cnum = self.cstore.alloc_new_crate_num(); - self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?; - info!( "register crate `{}` (cnum = {}. private_dep = {})", crate_root.name(), @@ -394,6 +416,14 @@ None }; + // Perform some verification *after* resolve_crate_deps() above is + // known to have been successful. It seems that - in error cases - the + // cstore can be in a temporarily invalid state between cnum allocation + // and dependency resolution and the verification code would produce + // ICEs in that case (see #83045). + self.verify_no_symbol_conflicts(&crate_root)?; + self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?; + let crate_metadata = CrateMetadata::new( self.sess, metadata, @@ -481,8 +511,11 @@ if dep.is_none() { self.used_extern_options.insert(name); } - self.maybe_resolve_crate(name, dep_kind, dep) - .unwrap_or_else(|err| err.report(self.sess, span)) + self.maybe_resolve_crate(name, dep_kind, dep).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) + }) } fn maybe_resolve_crate<'b>( @@ -736,7 +769,7 @@ } fn inject_profiler_runtime(&mut self, krate: &ast::Crate) { - if (self.sess.opts.debugging_opts.instrument_coverage + if (self.sess.instrument_coverage() || self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled()) && !self.sess.opts.debugging_opts.no_profiler_runtime @@ -899,11 +932,17 @@ // Don't worry about pathless `--extern foo` sysroot references continue; } - if self.used_extern_options.contains(&Symbol::intern(name)) { + let name_interned = Symbol::intern(name); + if self.used_extern_options.contains(&name_interned) { continue; } // Got a real unused --extern + if self.sess.opts.json_unused_externs { + self.cstore.unused_externs.push(name_interned); + continue; + } + let diag = match self.sess.opts.extern_dep_specs.get(name) { Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()), None => { @@ -936,9 +975,9 @@ self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); - info!("{:?}", CrateDump(&self.cstore)); - self.report_unused_deps(krate); + + info!("{:?}", CrateDump(&self.cstore)); } pub fn process_extern_crate( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,7 +5,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_internals)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] @@ -26,7 +26,6 @@ mod dependency_format; mod foreign_modules; -mod link_args; mod native_libs; mod rmeta; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/link_args.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/link_args.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/link_args.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/link_args.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::{sym, Symbol}; -use rustc_target::spec::abi::Abi; - -crate fn collect(tcx: TyCtxt<'_>) -> Vec { - let mut collector = Collector { tcx, args: Vec::new() }; - tcx.hir().krate().visit_all_item_likes(&mut collector); - - for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() { - if attr.has_name(sym::link_args) { - if let Some(linkarg) = attr.value_str() { - collector.add_link_args(linkarg); - } - } - } - - collector.args -} - -struct Collector<'tcx> { - tcx: TyCtxt<'tcx>, - args: Vec, -} - -impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - let abi = match it.kind { - hir::ItemKind::ForeignMod { abi, .. } => abi, - _ => return, - }; - if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - return; - } - - // First, add all of the custom #[link_args] attributes - let sess = &self.tcx.sess; - for m in - self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link_args)) - { - if let Some(linkarg) = m.value_str() { - self.add_link_args(linkarg); - } - } - } - - fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {} - fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {} - fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} -} - -impl<'tcx> Collector<'tcx> { - fn add_link_args(&mut self, args: Symbol) { - self.args.extend(args.as_str().split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string())) - } -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/locator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/locator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/locator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/locator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -216,6 +216,7 @@ use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; @@ -232,7 +233,6 @@ use snap::read::FrameDecoder; use std::io::{Read, Result as IoResult, Write}; -use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; use tracing::{debug, info, warn}; @@ -727,19 +727,6 @@ } } -/// A trivial wrapper for `Mmap` that implements `StableDeref`. -struct StableDerefMmap(memmap2::Mmap); - -impl Deref for StableDerefMmap { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.0.deref() - } -} - -unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {} - fn get_metadata_section( target: &Target, flavor: CrateFlavor, @@ -779,11 +766,11 @@ // mmap the file, because only a small fraction of it is read. let file = std::fs::File::open(filename) .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?; - let mmap = unsafe { memmap2::Mmap::map(&file) }; + let mmap = unsafe { Mmap::map(file) }; let mmap = mmap .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?; - rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box()) + rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) } }; let blob = MetadataBlob::new(raw_bytes); @@ -803,7 +790,8 @@ ) -> (PathBuf, CrateDisambiguator) { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, - Err(err) => err.report(sess, span), + // `core` is always available if we got as far as loading plugins. + Err(err) => err.report(sess, span, false), } } @@ -896,7 +884,7 @@ } impl CrateError { - crate fn report(self, sess: &Session, span: Span) -> ! { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { let mut err = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, @@ -1081,7 +1069,37 @@ if (crate_name == sym::std || crate_name == sym::core) && locator.triple != TargetTriple::from_triple(config::host_triple()) { - err.note(&format!("the `{}` target may not be installed", locator.triple)); + if missing_core { + err.note(&format!( + "the `{}` target may not be installed", + locator.triple + )); + } else { + err.note(&format!( + "the `{}` target may not support the standard library", + locator.triple + )); + } + if missing_core && std::env::var("RUSTUP_HOME").is_ok() { + err.help(&format!( + "consider downloading the target with `rustup target add {}`", + locator.triple + )); + } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. + // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. + // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help. + if !missing_core && span.is_dummy() { + let current_crate = + sess.opts.crate_name.as_deref().unwrap_or(""); + err.note(&format!( + "`std` is required by `{}` because it does not declare `#![no_std]`", + current_crate + )); + } + if sess.is_nightly_build() && std::env::var("CARGO").is_ok() { + err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + } } else if crate_name == sym::profiler_builtins { err.note(&"the compiler may have been built without the profiler runtime"); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,5 @@ use crate::creader::{CStore, LoadedMacro}; use crate::foreign_modules; -use crate::link_args; use crate::native_libs; use crate::rmeta::{self, encoder}; @@ -122,6 +121,7 @@ promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } + const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } @@ -294,10 +294,6 @@ foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect(); Lrc::new(modules) }, - link_args: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(link_args::collect(tcx)) - }, // Returns a map from a sufficiently visible external item (i.e., an // external item that is visible from at least one local module) to a diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/decoder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -7,7 +7,6 @@ use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; @@ -351,12 +350,6 @@ } } -impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { let cdata = decoder.cdata(); @@ -413,17 +406,17 @@ impl<'a, 'tcx> Decodable> for Span { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { + let ctxt = SyntaxContext::decode(decoder)?; let tag = u8::decode(decoder)?; - if tag == TAG_INVALID_SPAN { - return Ok(DUMMY_SP); + if tag == TAG_PARTIAL_SPAN { + return Ok(DUMMY_SP.with_ctxt(ctxt)); } debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); let lo = BytePos::decode(decoder)?; let len = BytePos::decode(decoder)?; - let ctxt = SyntaxContext::decode(decoder)?; let hi = lo + len; let sess = if let Some(sess) = decoder.sess { @@ -764,6 +757,7 @@ data.paren_sugar, data.has_auto_impl, data.is_marker, + data.skip_array_during_method_dispatch, data.specialization_kind, self.def_path_hash(item_id), ) @@ -774,6 +768,7 @@ false, false, false, + false, ty::trait_def::TraitSpecializationKind::None, self.def_path_hash(item_id), ), @@ -960,6 +955,14 @@ self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) } + fn get_const_param_default( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> rustc_middle::ty::Const<'tcx> { + self.root.tables.const_defaults.get(self, id).unwrap().decode((self, tcx)) + } + /// Iterates over all the stability attributes in the given crate. fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" @@ -1614,7 +1617,7 @@ .map(Path::new) .filter(|_| { // Only spend time on further checks if we have what to translate *to*. - sess.real_rust_source_base_dir.is_some() + sess.opts.real_rust_source_base_dir.is_some() }) .filter(|virtual_dir| { // Don't translate away `/rustc/$hash` if we're still remapping to it, @@ -1626,11 +1629,11 @@ debug!( "try_to_translate_virtual_to_real(name={:?}): \ virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}", - name, virtual_rust_source_base_dir, sess.real_rust_source_base_dir, + name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir, ); if let Some(virtual_dir) = virtual_rust_source_base_dir { - if let Some(real_dir) = &sess.real_rust_source_base_dir { + if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { if let rustc_span::FileName::Real(old_name) = name { if let rustc_span::RealFileName::Named(one_path) = old_name { if let Ok(rest) = one_path.strip_prefix(virtual_dir) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/encoder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/encoder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/encoder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/encoder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,6 @@ use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; @@ -116,6 +115,7 @@ emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -184,11 +184,48 @@ impl<'a, 'tcx> Encodable> for Span { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { - if *self == rustc_span::DUMMY_SP { - return TAG_INVALID_SPAN.encode(s); + let span = self.data(); + + // Don't serialize any `SyntaxContext`s from a proc-macro crate, + // since we don't load proc-macro dependencies during serialization. + // This means that any hygiene information from macros used *within* + // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro + // definition) will be lost. + // + // This can show up in two ways: + // + // 1. Any hygiene information associated with identifier of + // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. + // Since proc-macros can only be invoked from a different crate, + // real code should never need to care about this. + // + // 2. Using `Span::def_site` or `Span::mixed_site` will not + // include any hygiene information associated with the definition + // site. This means that a proc-macro cannot emit a `$crate` + // identifier which resolves to one of its dependencies, + // which also should never come up in practice. + // + // Additionally, this affects `Span::parent`, and any other + // span inspection APIs that would otherwise allow traversing + // the `SyntaxContexts` associated with a span. + // + // None of these user-visible effects should result in any + // cross-crate inconsistencies (getting one behavior in the same + // crate, and a different behavior in another crate) due to the + // limited surface that proc-macros can expose. + // + // IMPORTANT: If this is ever changed, be sure to update + // `rustc_span::hygiene::raw_encode_expn_id` to handle + // encoding `ExpnData` for proc-macro crates. + if s.is_proc_macro { + SyntaxContext::root().encode(s)?; + } else { + span.ctxt.encode(s)?; } - let span = self.data(); + if self.is_dummy() { + return TAG_PARTIAL_SPAN.encode(s); + } // The Span infrastructure should make sure that this invariant holds: debug_assert!(span.lo <= span.hi); @@ -203,7 +240,7 @@ if !s.source_file_cache.0.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_INVALID_SPAN.encode(s); + return TAG_PARTIAL_SPAN.encode(s); } let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); @@ -259,43 +296,6 @@ let len = hi - lo; len.encode(s)?; - // Don't serialize any `SyntaxContext`s from a proc-macro crate, - // since we don't load proc-macro dependencies during serialization. - // This means that any hygiene information from macros used *within* - // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro - // definition) will be lost. - // - // This can show up in two ways: - // - // 1. Any hygiene information associated with identifier of - // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. - // Since proc-macros can only be invoked from a different crate, - // real code should never need to care about this. - // - // 2. Using `Span::def_site` or `Span::mixed_site` will not - // include any hygiene information associated with the definition - // site. This means that a proc-macro cannot emit a `$crate` - // identifier which resolves to one of its dependencies, - // which also should never come up in practice. - // - // Additionally, this affects `Span::parent`, and any other - // span inspection APIs that would otherwise allow traversing - // the `SyntaxContexts` associated with a span. - // - // None of these user-visible effects should result in any - // cross-crate inconsistencies (getting one behavior in the same - // crate, and a different behavior in another crate) due to the - // limited surface that proc-macros can expose. - // - // IMPORTANT: If this is ever changed, be sure to update - // `rustc_span::hygiene::raw_encode_expn_id` to handle - // encoding `ExpnData` for proc-macro crates. - if s.is_proc_macro { - SyntaxContext::root().encode(s)?; - } else { - span.ctxt.encode(s)?; - } - if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` @@ -307,12 +307,6 @@ } } -impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { - self.opaque.encode_fingerprint(f) - } -} - impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; @@ -433,7 +427,7 @@ fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); - self.encode_info_for_mod(CRATE_DEF_ID, &krate.item.module); + self.encode_info_for_mod(CRATE_DEF_ID, &krate.item); // Proc-macro crates only export proc-macro items, which are looked // up using `proc_macro_data` @@ -1428,6 +1422,7 @@ paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, + skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch, specialization_kind: trait_def.specialization_kind, }; @@ -1882,13 +1877,12 @@ default.is_some(), ); } - GenericParamKind::Const { .. } => { - self.encode_info_for_generic_param( - def_id.to_def_id(), - EntryKind::ConstParam, - true, - ); - // FIXME(const_generics_defaults) + GenericParamKind::Const { ref default, .. } => { + let def_id = def_id.to_def_id(); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); + if default.is_some() { + record!(self.tables.const_defaults[def_id] <- self.tcx.const_param_default(def_id)) + } } } } @@ -2064,10 +2058,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); - encoder.emit_raw_bytes(METADATA_HEADER); + encoder.emit_raw_bytes(METADATA_HEADER).unwrap(); // Will be filled with the root position after encoding everything. - encoder.emit_raw_bytes(&[0, 0, 0, 0]); + encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap(); let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (source_map_files[0].clone(), 0); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -307,13 +307,14 @@ mir_for_ctfe: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, + const_defaults: Table>>, unused_generic_params: Table>>, // `def_keys` and `def_path_hashes` represent a lazy version of a // `DefPathTable`. This allows us to avoid deserializing an entire // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - def_path_hashes: Table> + def_path_hashes: Table>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] @@ -384,6 +385,7 @@ paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + skip_array_during_method_dispatch: bool, specialization_kind: ty::trait_def::TraitSpecializationKind, } @@ -448,4 +450,4 @@ // Tags used for encoding Spans: const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; -const TAG_INVALID_SPAN: u8 = 2; +const TAG_PARTIAL_SPAN: u8 = 2; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/table.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/table.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/table.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_metadata/src/rmeta/table.rs 2021-06-17 03:53:50.000000000 +0000 @@ -2,6 +2,7 @@ use rustc_index::vec::Idx; use rustc_serialize::opaque::Encoder; +use rustc_serialize::Encoder as _; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -172,7 +173,7 @@ pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy> { let pos = buf.position(); - buf.emit_raw_bytes(&self.bytes); + buf.emit_raw_bytes(&self.bytes).unwrap(); Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len()) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/dep_node.rs 2021-06-17 03:53:50.000000000 +0000 @@ -32,8 +32,8 @@ //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro //! defines the `DepKind` enum. Each `DepKind` has its own parameters that are //! needed at runtime in order to construct a valid `DepNode` fingerprint. -//! However, only `CompileCodegenUnit` is constructed explicitly (with -//! `make_compile_codegen_unit`). +//! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed +//! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`). //! //! Because the macro sees what parameters a given `DepKind` requires, it can //! "infer" some properties for each kind of `DepNode`: @@ -46,15 +46,17 @@ //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. //! -//! `make_compile_codegen_unit`, together with `DepNode::new()`, ensures that only -//! valid `DepNode` instances can be constructed. For example, the API does not -//! allow for constructing parameterless `DepNode`s with anything other -//! than a zeroed out fingerprint. More generally speaking, it relieves the -//! user of the `DepNode` API of having to know how to compute the expected -//! fingerprint for a given set of node parameters. +//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with +//! `DepNode::new()`, ensures that only valid `DepNode` instances can be +//! constructed. For example, the API does not allow for constructing +//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. +//! More generally speaking, it relieves the user of the `DepNode` API of +//! having to know how to compute the expected fingerprint for a given set of +//! node parameters. //! //! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html +use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; @@ -175,6 +177,14 @@ can_reconstruct_query_key: || false, }; + pub const CompileMonoItem: DepKindStruct = DepKindStruct { + has_params: true, + is_anon: false, + is_eval_always: false, + + can_reconstruct_query_key: || false, + }; + macro_rules! define_query_dep_kinds { ($( [$($attrs:tt)*] @@ -251,6 +261,10 @@ // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below. [] CompileCodegenUnit(Symbol), + + // WARNING: if `MonoItem` is changed, make sure you update `make_compile_mono_item` below. + // Only used by rustc_codegen_cranelift + [] CompileMonoItem(MonoItem), ]); // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. @@ -259,6 +273,12 @@ DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name) } +// 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 { + DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) +} + pub type DepNode = rustc_query_system::dep_graph::DepNode; // We keep a lot of `DepNode`s in memory during compilation. It's not diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/dep_graph/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -8,18 +8,19 @@ mod dep_node; pub use rustc_query_system::dep_graph::{ - debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex, - WorkProduct, WorkProductId, + debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex, + SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -crate use dep_node::make_compile_codegen_unit; pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; +crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph; pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; +pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/hir/map/collector.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/hir/map/collector.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/hir/map/collector.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/hir/map/collector.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ use crate::arena::Arena; use crate::hir::map::{Entry, HirOwnerData, Map}; -use crate::hir::{Owner, OwnerNodes, ParentedNode}; +use crate::hir::{AttributeMap, Owner, OwnerNodes, ParentedNode}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; use rustc_data_structures::fingerprint::Fingerprint; @@ -9,7 +9,7 @@ use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_INDEX; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{self, DefPathHash}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; @@ -58,18 +58,28 @@ fn hash_body( hcx: &mut StableHashingContext<'_>, + def_id: LocalDefId, def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, + krate: &Crate<'_>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, ) -> Fingerprint { - let hash = { + // Hash of nodes. + let hash: Fingerprint = { let mut stable_hasher = StableHasher::new(); hcx.while_hashing_hir_bodies(true, |hcx| { item_like.hash_stable(hcx, &mut stable_hasher); }); stable_hasher.finish() }; - hir_body_nodes.push((def_path_hash, hash)); + // Hash for crate_hash. + let hash_with_attrs: Fingerprint = { + let mut hasher = StableHasher::new(); + hash.hash_stable(hcx, &mut hasher); + AttributeMap { map: &krate.attrs, prefix: def_id }.hash_stable(hcx, &mut hasher); + hasher.finish() + }; + hir_body_nodes.push((def_path_hash, hash_with_attrs)); hash } @@ -120,7 +130,14 @@ attrs: _, } = *krate; - hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) + hash_body( + &mut hcx, + CRATE_DEF_ID, + root_mod_def_path_hash, + item, + krate, + &mut hir_body_nodes, + ) }; let mut collector = NodeCollector { @@ -186,6 +203,7 @@ let crate_hash_input = ( ((node_hashes, upstream_crates), source_file_names), (commandline_args_hash, crate_disambiguator.to_fingerprint()), + &self.krate.non_exported_macro_attrs, ); let mut stable_hasher = StableHasher::new(); @@ -297,7 +315,14 @@ let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); + let hash = hash_body( + &mut self.hcx, + dep_node_owner, + def_path_hash, + item_like, + self.krate, + &mut self.hir_body_nodes, + ); self.current_dep_node_owner = dep_node_owner; f(self, hash); @@ -373,26 +398,12 @@ } fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) { - if let hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } = param.kind - { - debug_assert_eq!( - param.hir_id.owner, - self.definitions.opt_hir_id_to_local_def_id(param.hir_id).unwrap() - ); - self.with_dep_node_owner(param.hir_id.owner, param, |this, hash| { - this.insert_with_hash(param.span, param.hir_id, Node::GenericParam(param), hash); + self.insert(param.span, param.hir_id, Node::GenericParam(param)); + intravisit::walk_generic_param(self, param); + } - this.with_parent(param.hir_id, |this| { - intravisit::walk_generic_param(this, param); - }); - }); - } else { - self.insert(param.span, param.hir_id, Node::GenericParam(param)); - intravisit::walk_generic_param(self, param); - } + fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) { + self.with_parent(param, |this| intravisit::walk_const_param_default(this, ct)) } fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/hir/map/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/hir/map/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/hir/map/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/hir/map/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -459,7 +459,7 @@ let hir_id = self.local_def_id_to_hir_id(module); match self.get_entry(hir_id).node { Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), - Node::Crate(item) => (&item.module, item.span, hir_id), + Node::Crate(item) => (&item, item.inner, hir_id), node => panic!("not a module: {:?}", node), } } @@ -550,24 +550,6 @@ ParentHirIterator { current_id, map: self } } - /// Checks if the node is an argument. An argument is a local variable whose - /// immediate parent is an item or a closure. - pub fn is_argument(&self, id: HirId) -> bool { - match self.find(id) { - Some(Node::Binding(_)) => (), - _ => return false, - } - matches!( - self.find(self.get_parent_node(id)), - Some( - Node::Item(_) - | Node::TraitItem(_) - | Node::ImplItem(_) - | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }), - ) - ) - } - /// Checks if the node is left-hand side of an assignment. pub fn is_lhs(&self, id: HirId) -> bool { match self.find(self.get_parent_node(id)) { @@ -779,17 +761,6 @@ } } - pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData<'hir> { - match self.find(id) { - Some( - Node::Ctor(vd) - | Node::Item(Item { kind: ItemKind::Struct(vd, _) | ItemKind::Union(vd, _), .. }), - ) => vd, - Some(Node::Variant(variant)) => &variant.data, - _ => bug!("expected struct or variant, found {}", self.node_to_string(id)), - } - } - pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> { match self.find(id) { Some(Node::Variant(variant)) => variant, @@ -897,7 +868,7 @@ Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, Node::MacroDef(macro_def) => macro_def.span, - Node::Crate(item) => item.span, + Node::Crate(item) => item.inner, }; Some(span) } @@ -972,7 +943,7 @@ intravisit::walk_crate(&mut collector, tcx.untracked_crate); let crate_disambiguator = tcx.sess.local_crate_disambiguator(); - let cmdline_args = tcx.sess.opts.dep_tracking_hash(); + let cmdline_args = tcx.sess.opts.dep_tracking_hash(true); collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/hcx.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/hcx.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/hcx.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/hcx.rs 2021-06-17 03:53:50.000000000 +0000 @@ -120,11 +120,6 @@ } #[inline] - pub fn sess(&self) -> &'a Session { - self.sess - } - - #[inline] pub fn while_hashing_hir_bodies(&mut self, hash_bodies: bool, f: F) { let prev_hash_bodies = self.hash_bodies; self.hash_bodies = hash_bodies; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_syntax.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_syntax.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_syntax.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_syntax.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,5 @@ //! This module contains `HashStable` implementations for various data types -//! from librustc_ast in no particular order. +//! from `rustc_ast` in no particular order. use crate::ich::StableHashingContext; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_ty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_ty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_ty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ich/impls_ty.rs 2021-06-17 03:53:50.000000000 +0000 @@ -70,16 +70,16 @@ ty::ReEmpty(universe) => { universe.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { db.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => { db.hash_stable(hcx, hasher); def_id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => { db.hash_stable(hcx, hasher); } ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { @@ -118,12 +118,13 @@ } } -impl<'a, T> HashStable> for ty::Binder +impl<'a, 'tcx, T> HashStable> for ty::Binder<'tcx, T> where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.as_ref().skip_binder().hash_stable(hcx, hasher); + self.bound_vars().hash_stable(hcx, hasher); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/infer/canonical.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/infer/canonical.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/infer/canonical.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/infer/canonical.rs 2021-06-17 03:53:50.000000000 +0000 @@ -27,6 +27,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; +use std::iter; use std::ops::Index; /// A "canonicalized" type `V` is one where all free inference @@ -227,20 +228,12 @@ Certainty::Ambiguous => false, } } - - pub fn is_ambiguous(&self) -> bool { - !self.is_proven() - } } impl<'tcx, R> QueryResponse<'tcx, R> { pub fn is_proven(&self) -> bool { self.certainty.is_proven() } - - pub fn is_ambiguous(&self) -> bool { - !self.is_proven() - } } impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> { @@ -284,7 +277,7 @@ } pub type QueryOutlivesConstraint<'tcx> = - ty::Binder, Region<'tcx>>>; + ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>; TrivialTypeFoldableAndLiftImpls! { for <'tcx> { @@ -315,16 +308,14 @@ use crate::ty::subst::GenericArgKind; CanonicalVarValues { - var_values: self - .var_values - .iter() - .zip(0..) + var_values: iter::zip(&self.var_values, 0..) .map(|(kind, i)| match kind.unpack() { GenericArgKind::Type(..) => { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() } GenericArgKind::Lifetime(..) => { - let br = ty::BoundRegion { kind: ty::BrAnon(i) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/infer/unify_key.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/infer/unify_key.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/infer/unify_key.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/infer/unify_key.rs 2021-06-17 03:53:50.000000000 +0000 @@ -97,13 +97,6 @@ ConstVariableValue::Known { value } => Some(value), } } - - pub fn is_unknown(&self) -> bool { - match *self { - ConstVariableValue::Unknown { .. } => true, - ConstVariableValue::Known { .. } => false, - } - } } #[derive(Copy, Clone, Debug)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -28,8 +28,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(cmp_min_max_by)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(core_intrinsics)] #![feature(discriminant_kind)] @@ -37,7 +35,7 @@ #![feature(extern_types)] #![feature(nll)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(min_specialization)] #![feature(trusted_len)] #![feature(test)] @@ -50,6 +48,7 @@ #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] +#![feature(iter_zip)] #![recursion_limit = "512"] #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ use crate::mir::mono::Linkage; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_session::config::SanitizerSet; use rustc_span::symbol::Symbol; +use rustc_target::spec::SanitizerSet; #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] pub struct CodegenFnAttrs { @@ -86,6 +86,10 @@ /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. const CMSE_NONSECURE_ENTRY = 1 << 14; + /// `#[no_coverage]`: indicates that the function should be ignored by + /// the MIR `InstrumentCoverage` pass and not added to the coverage map + /// during codegen. + const NO_COVERAGE = 1 << 15; } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/limits.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/limits.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/limits.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/limits.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,8 @@ -//! Registering limits, recursion_limit, type_length_limit and const_eval_limit +//! Registering limits: +//! * recursion_limit, +//! * move_size_limit, +//! * type_length_limit, and +//! * const_eval_limit //! //! There are various parts of the compiler that must impose arbitrary limits //! on how deeply they recurse to prevent stack overflow. Users can override @@ -8,13 +12,14 @@ use crate::bug; use rustc_ast as ast; use rustc_data_structures::sync::OnceCell; -use rustc_session::{Limit, Session}; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use std::num::IntErrorKind; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); + update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000); } @@ -22,7 +27,7 @@ fn update_limit( sess: &Session, krate: &ast::Crate, - limit: &OnceCell, + limit: &OnceCell + std::fmt::Debug>, name: Symbol, default: usize, ) { @@ -34,7 +39,7 @@ if let Some(s) = attr.value_str() { match s.as_str().parse() { Ok(n) => { - limit.set(Limit::new(n)).unwrap(); + limit.set(From::from(n)).unwrap(); return; } Err(e) => { @@ -63,5 +68,5 @@ } } } - limit.set(Limit::new(default)).unwrap(); + limit.set(From::from(default)).unwrap(); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/region.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/region.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/region.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/region.rs 2021-06-17 03:53:50.000000000 +0000 @@ -235,18 +235,6 @@ /// escape into 'static and should have no local cleanup scope. rvalue_scopes: FxHashMap>, - /// Encodes the hierarchy of fn bodies. Every fn body (including - /// closures) forms its own distinct region hierarchy, rooted in - /// the block that is the fn body. This map points from the ID of - /// that root block to the ID of the root block for the enclosing - /// fn, if any. Thus the map structures the fn bodies into a - /// hierarchy based on their lexical mapping. This is used to - /// handle the relationships between regions in a fn and in a - /// closure defined by that fn. See the "Modeling closures" - /// section of the README in infer::region_constraints for - /// more details. - closure_tree: FxHashMap, - /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the /// postorder of the Visitor traversal on the HIR. @@ -356,23 +344,6 @@ self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_closure` is defined within `sup_closure`. These IDs - /// should be the ID of the block that is the fn body, which is - /// also the root of the region hierarchy for that fn. - pub fn record_closure_parent( - &mut self, - sub_closure: hir::ItemLocalId, - sup_closure: hir::ItemLocalId, - ) { - debug!( - "record_closure_parent(sub_closure={:?}, sup_closure={:?})", - sub_closure, sup_closure - ); - assert!(sub_closure != sup_closure); - let previous = self.closure_tree.insert(sub_closure, sup_closure); - assert!(previous.is_none()); - } - pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.item_local_id()); @@ -430,6 +401,8 @@ /// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and /// `false` otherwise. + /// + /// Used by clippy. pub fn is_subscope_of(&self, subscope: Scope, superscope: Scope) -> bool { let mut s = subscope; debug!("is_subscope_of({:?}, {:?})", subscope, superscope); @@ -472,7 +445,6 @@ ref var_map, ref destruction_scopes, ref rvalue_scopes, - ref closure_tree, ref yield_in_scope, } = *self; @@ -486,7 +458,6 @@ var_map.hash_stable(hcx, hasher); destruction_scopes.hash_stable(hcx, hasher); rvalue_scopes.hash_stable(hcx, hasher); - closure_tree.hash_stable(hcx, hasher); yield_in_scope.hash_stable(hcx, hasher); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/resolve_lifetime.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/resolve_lifetime.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/resolve_lifetime.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/resolve_lifetime.rs 2021-06-17 03:53:50.000000000 +0000 @@ -39,8 +39,13 @@ pub enum Region { Static, EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32), + LateBound( + ty::DebruijnIndex, + /* late-bound index */ u32, + /* lifetime decl */ DefId, + LifetimeDefOrigin, + ), + LateBoundAnon(ty::DebruijnIndex, /* late-bound index */ u32, /* anon index */ u32), Free(DefId, /* lifetime decl */ DefId), } @@ -79,8 +84,5 @@ /// (b) it DOES appear in the arguments. pub late_bound: FxHashMap>, - /// For each type and trait definition, maps type parameters - /// to the trait object lifetime defaults computed from them. - pub object_lifetime_defaults: - FxHashMap>>, + pub late_bound_vars: FxHashMap>>, } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/stability.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/stability.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/middle/stability.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/middle/stability.rs 2021-06-17 03:53:50.000000000 +0000 @@ -29,12 +29,6 @@ Stable, } -impl StabilityLevel { - pub fn from_attr_level(level: &attr::StabilityLevel) -> Self { - if level.is_stable() { Stable } else { Unstable } - } -} - /// An entry in the `depr_map`. #[derive(Clone, HashStable, Debug)] pub struct DeprecationEntry { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/abstract_const.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/abstract_const.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/abstract_const.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/abstract_const.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,3 +18,20 @@ UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum NotConstEvaluatable { + Error(rustc_errors::ErrorReported), + MentionsInfer, + MentionsParam, +} + +impl From for NotConstEvaluatable { + fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable { + NotConstEvaluatable::Error(e) + } +} + +TrivialTypeFoldableAndLiftImpls! { + NotConstEvaluatable, +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/coverage.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/coverage.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/coverage.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/coverage.rs 2021-06-17 03:53:50.000000000 +0000 @@ -41,8 +41,16 @@ } impl CounterValueReference { - // Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. + /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. pub const START: Self = Self::from_u32(1); + + /// Returns explicitly-requested zero-based version of the counter id, used + /// during codegen. LLVM expects zero-based indexes. + pub fn zero_based_index(&self) -> u32 { + let one_based_index = self.as_u32(); + debug_assert!(one_based_index > 0); + one_based_index - 1 + } } rustc_index::newtype_index! { @@ -117,17 +125,9 @@ } } - pub fn is_counter(&self) -> bool { - matches!(self, Self::Counter { .. }) - } - pub fn is_expression(&self) -> bool { matches!(self, Self::Expression { .. }) } - - pub fn is_unreachable(&self) -> bool { - *self == Self::Unreachable - } } impl Debug for CoverageKind { @@ -183,3 +183,13 @@ Subtract, Add, } + +impl Op { + pub fn is_add(&self) -> bool { + matches!(self, Self::Add) + } + + pub fn is_subtract(&self) -> bool { + matches!(self, Self::Subtract) + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/error.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/error.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/error.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/error.rs 2021-06-17 03:53:50.000000000 +0000 @@ -45,8 +45,8 @@ /// Packages the kind of error we got from the const code interpreter /// up with a Rust-level backtrace of where the error occurred. -/// Thsese should always be constructed by calling `.into()` on -/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*` +/// These should always be constructed by calling `.into()` on +/// a `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*` /// macros for this. #[derive(Debug)] pub struct InterpErrorInfo<'tcx>(Box>); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/queries.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/queries.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/queries.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/queries.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ use super::{ErrorHandled, EvalToConstValueResult, GlobalId}; use crate::mir; -use crate::ty::subst::{InternalSubsts, SubstsRef}; +use crate::ty::subst::InternalSubsts; use crate::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::Span; @@ -35,14 +35,12 @@ pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, - promoted: Option, + ct: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) { + match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted }; + let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) } Ok(None) => Err(ErrorHandled::TooGeneric), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/value.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/value.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/value.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/interpret/value.rs 2021-06-17 03:53:50.000000000 +0000 @@ -308,16 +308,6 @@ } #[inline] - pub fn from_i8(i: i8) -> Self { - Self::from_int(i, Size::from_bits(8)) - } - - #[inline] - pub fn from_i16(i: i16) -> Self { - Self::from_int(i, Size::from_bits(16)) - } - - #[inline] pub fn from_i32(i: i32) -> Self { Self::from_int(i, Size::from_bits(32)) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -12,10 +12,10 @@ use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; -use rustc_hir as hir; 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_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; @@ -379,24 +379,6 @@ } } - /// Returns an iterator over all temporaries. - #[inline] - pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); - if self.local_decls[local].is_user_variable() { None } else { Some(local) } - }) - } - - /// Returns an iterator over all user-declared locals. - #[inline] - pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); - self.local_decls[local].is_user_variable().then_some(local) - }) - } - /// Returns an iterator over all user-declared mutable locals. #[inline] pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { @@ -1231,7 +1213,7 @@ out_place: Option>, }, Const { - value: Operand<'tcx>, + value: Box>, }, SymFn { value: Box>, @@ -1500,7 +1482,7 @@ /// /// Note that this also is emitted for regular `let` bindings to ensure that locals that are /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` - FakeRead(FakeReadCause, Box>), + FakeRead(Box<(FakeReadCause, Place<'tcx>)>), /// Write the discriminant for a variant to the enum Place. SetDiscriminant { place: Box>, variant_index: VariantIdx }, @@ -1537,9 +1519,10 @@ AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), /// Marks the start of a "coverage region", injected with '-Zinstrument-coverage'. A - /// `CoverageInfo` statement carries metadata about the coverage region, used to inject a coverage - /// map into the binary. The `Counter` kind also generates executable code, to increment a - /// counter varible at runtime, each time the code region is executed. + /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage + /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates + /// executable code, to increment a counter variable at runtime, each time the code region is + /// executed. Coverage(Box), /// Denotes a call to the intrinsic function copy_overlapping, where `src_dst` denotes the @@ -1592,7 +1575,12 @@ /// `let x: !; match x {}` doesn't generate any read of x so we need to /// generate a read of x to check that it is initialized and safe. - ForMatchedPlace, + /// + /// If a closure pattern matches a Place starting with an Upvar, then we introduce a + /// FakeRead for that Place outside the closure, in such a case this option would be + /// Some(closure_def_id). + /// Otherwise, the value of the optional DefId will be None. + ForMatchedPlace(Option), /// A fake read of the RefWithinGuard version of a bind-by-value variable /// in a match guard to ensure that it's value hasn't change by the time @@ -1611,7 +1599,12 @@ /// but in some cases it can affect the borrow checker, as in #53695. /// Therefore, we insert a "fake read" here to ensure that we get /// appropriate errors. - ForLet, + /// + /// If a closure pattern matches a Place starting with an Upvar, then we introduce a + /// FakeRead for that Place outside the closure, in such a case this option would be + /// Some(closure_def_id). + /// Otherwise, the value of the optional DefId will be None. + ForLet(Option), /// If we have an index expression like /// @@ -1635,7 +1628,9 @@ use self::StatementKind::*; match self.kind { Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv), - FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place), + FakeRead(box (ref cause, ref place)) => { + write!(fmt, "FakeRead({:?}, {:?})", cause, place) + } Retag(ref kind, ref place) => write!( fmt, "Retag({}{:?})", @@ -1953,6 +1948,29 @@ } } +impl SourceScope { + /// 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( + self, + source_scopes: &IndexVec>, + ) -> Option { + let mut data = &source_scopes[self]; + // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it + // does not work as I thought it would. Needs more investigation and documentation. + while data.inlined.is_some() { + trace!(?data); + data = &source_scopes[data.parent_scope.unwrap()]; + } + trace!(?data); + match &data.local_data { + ClearCrossCrate::Set(data) => Some(data.lint_root), + ClearCrossCrate::Clear => None, + } + } +} + #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] pub struct SourceScopeData<'tcx> { pub span: Span, @@ -2328,7 +2346,7 @@ CtorKind::Fn => fmt_tuple(fmt, &name), CtorKind::Fictive => { let mut struct_fmt = fmt.debug_struct(&name); - for (field, place) in variant_def.fields.iter().zip(places) { + for (field, place) in iter::zip(&variant_def.fields, places) { struct_fmt.field(&field.ident.as_str(), place); } struct_fmt.finish() @@ -2352,7 +2370,7 @@ let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + 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); } @@ -2371,7 +2389,7 @@ let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + 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); } @@ -2409,7 +2427,8 @@ pub literal: ConstantKind<'tcx>, } -#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Lift)] pub enum ConstantKind<'tcx> { /// This constant came from the type system Ty(&'tcx ty::Const<'tcx>), @@ -2708,7 +2727,13 @@ ty::FnDef(..) => {} _ => write!(fmt, "const ")?, } - match self.literal { + Display::fmt(&self.literal, fmt) + } +} + +impl<'tcx> Display for ConstantKind<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + match *self { ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/mono.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/mono.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/mono.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/mono.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::{HirId, ItemId}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; @@ -93,7 +93,7 @@ // indicator, then we'll be creating a globally shared version. if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator() || !instance.def.generates_cgu_internal_copy(tcx) - || Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id) + || Some(instance.def_id()) == entry_def_id { return InstantiationMode::GloballyShared { may_conflict: false }; } @@ -181,6 +181,11 @@ } .map(|hir_id| tcx.hir().span(hir_id)) } + + // Only used by rustc_codegen_cranelift + pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { + crate::dep_graph::make_compile_mono_item(tcx, self) + } } impl<'a, 'tcx> HashStable> for MonoItem<'tcx> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/query.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/query.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/query.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/query.rs 2021-06-17 03:53:50.000000000 +0000 @@ -19,19 +19,11 @@ #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationKind { - /// Only permitted in regular `fn`s, prohibited in `const fn`s. + /// Unsafe operation outside `unsafe`. General, - /// Permitted both in `const fn`s and regular `fn`s. - GeneralAndConstFn, - /// Borrow of packed field. - /// Has to be handled as a lint for backwards compatibility. - BorrowPacked, /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. /// Has to be handled as a lint for backwards compatibility. UnsafeFn, - /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block. - /// Has to be handled as a lint for backwards compatibility. - UnsafeFnBorrowPacked, } #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/terminator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/terminator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/terminator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/terminator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -67,7 +67,7 @@ /// /// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory. pub fn iter(&self) -> SwitchTargetsIter<'_> { - SwitchTargetsIter { inner: self.values.iter().zip(self.targets.iter()) } + SwitchTargetsIter { inner: iter::zip(&self.values, &self.targets) } } /// Returns a slice with all possible jump targets (including the fallback target). diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/traversal.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/traversal.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/traversal.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/traversal.rs 2021-06-17 03:53:50.000000000 +0000 @@ -264,10 +264,6 @@ ReversePostorder { body, blocks, idx: len } } - - pub fn reset(&mut self) { - self.idx = self.blocks.len(); - } } pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorder<'a, 'tcx> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/type_foldable.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/type_foldable.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/type_foldable.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/type_foldable.rs 2021-06-17 03:53:50.000000000 +0000 @@ -348,6 +348,11 @@ } impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { + #[inline(always)] + fn fold_with>(self, folder: &mut F) -> Self { + folder.fold_mir_const(self) + } + fn super_fold_with>(self, folder: &mut F) -> Self { match self { ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/visit.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/visit.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/mir/visit.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/mir/visit.rs 2021-06-17 03:53:50.000000000 +0000 @@ -380,7 +380,7 @@ ) => { self.visit_assign(place, rvalue, location); } - StatementKind::FakeRead(_, place) => { + StatementKind::FakeRead(box (_, place)) => { self.visit_place( place, PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), @@ -584,8 +584,7 @@ } => { for op in operands { match op { - InlineAsmOperand::In { value, .. } - | InlineAsmOperand::Const { value } => { + InlineAsmOperand::In { value, .. } => { self.visit_operand(value, location); } InlineAsmOperand::Out { place, .. } => { @@ -607,7 +606,8 @@ ); } } - InlineAsmOperand::SymFn { value } => { + InlineAsmOperand::Const { value } + | InlineAsmOperand::SymFn { value } => { self.visit_constant(value, location); } InlineAsmOperand::SymStatic { def_id: _ } => {} @@ -1247,12 +1247,6 @@ matches!(self, PlaceContext::MutatingUse(..)) } - /// Returns `true` if this place context represents a use that does not change the value. - #[inline] - pub fn is_nonmutating_use(&self) -> bool { - matches!(self, PlaceContext::NonMutatingUse(..)) - } - /// Returns `true` if this place context represents a use. #[inline] pub fn is_use(&self) -> bool { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/query/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/query/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/query/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/query/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -93,6 +93,12 @@ desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Given the def_id of a const-generic parameter, computes the associated default const + /// parameter. e.g. `fn example` called on `N` would return `3`. + query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { + desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) } @@ -328,7 +334,10 @@ /// Returns the name of the file that contains the function body, if instrumented for coverage. query covered_file_name(key: DefId) -> Option { - desc { |tcx| "retrieving the covered file name, if instrumented, for `{}`", tcx.def_path_str(key) } + desc { + |tcx| "retrieving the covered file name, if instrumented, for `{}`", + tcx.def_path_str(key) + } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } } @@ -336,7 +345,10 @@ /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the /// function was optimized out before codegen, and before being added to the Coverage Map. query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> { - desc { |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", tcx.def_path_str(key) } + desc { + |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", + tcx.def_path_str(key) + } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } } @@ -552,7 +564,7 @@ } /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> ty::AssociatedItems<'tcx> { + query associated_items(key: DefId) -> ty::AssocItems<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } @@ -993,6 +1005,10 @@ query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } } + /// Query backing `TyS::is_unpin`. + query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Unpin`", env.value } + } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } @@ -1039,6 +1055,8 @@ desc { "checking if the crate is_compiler_builtins" } } query has_global_allocator(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always fatal_cycle desc { "checking if the crate has_global_allocator" } } @@ -1176,7 +1194,7 @@ /// Identifies the entry-point (e.g., the `main` function) for a given /// crate, returning `None` if there is no entry point (such as for library crates). - query entry_fn(_: CrateNum) -> Option<(LocalDefId, EntryFnType)> { + query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } query plugin_registrar_fn(_: CrateNum) -> Option { @@ -1237,13 +1255,19 @@ desc { |tcx| "native_library_kind({})", tcx.def_path_str(def_id) } } - query link_args(_: CrateNum) -> Lrc> { - eval_always - desc { "looking up link arguments for a crate" } - } - - /// Lifetime resolution. See `middle::resolve_lifetimes`. - query resolve_lifetimes(_: CrateNum) -> ResolveLifetimes { + /// Does lifetime resolution, but does not descend into trait items. This + /// should only be used for resolving lifetimes of on trait definitions, + /// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits + /// the same lifetimes and is responsible for diagnostics. + /// See `rustc_resolve::late::lifetimes for details. + query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes { + storage(ArenaCacheSelector<'tcx>) + desc { "resolving lifetimes for a trait definition" } + } + /// Does lifetime resolution on items. Importantly, we can't resolve + /// lifetimes directly on things like trait methods, because of trait params. + /// See `rustc_resolve::late::lifetimes for details. + query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes { storage(ArenaCacheSelector<'tcx>) desc { "resolving lifetimes" } } @@ -1255,9 +1279,17 @@ Option<(LocalDefId, &'tcx FxHashSet)> { desc { "testing if a region is late bound" } } + /// For a given item (like a struct), gets the default lifetimes to be used + /// for each parameter if a trait object were to be passed for that parameter. + /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. + /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. query object_lifetime_defaults_map(_: LocalDefId) - -> Option<&'tcx FxHashMap>> { - desc { "looking up lifetime defaults for a region" } + -> Option> { + desc { "looking up lifetime defaults for a region on an item" } + } + query late_bound_vars_map(_: LocalDefId) + -> Option<&'tcx FxHashMap>> { + desc { "looking up late bound vars" } } query visibility(def_id: DefId) -> ty::Visibility { @@ -1451,6 +1483,13 @@ desc { "normalizing `{}`", goal.value } } + /// Do not call this query directly: invoke `normalize_erasing_regions` instead. + query normalize_mir_const_after_erasing_regions( + goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + ) -> mir::ConstantKind<'tcx> { + desc { "normalizing `{}`", goal.value } + } + query implied_outlives_bounds( goal: CanonicalTyGoal<'tcx> ) -> Result< diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/traits/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/traits/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/traits/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/traits/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -9,7 +9,7 @@ mod structural_impls; use crate::infer::canonical::Canonical; -use crate::mir::interpret::ErrorHandled; +use crate::mir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; @@ -323,6 +323,9 @@ /// #[feature(trivial_bounds)] is not enabled TrivialBound, + + /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` + OpaqueType, } impl ObligationCauseCode<'_> { @@ -341,7 +344,7 @@ // `ObligationCauseCode` 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!(ObligationCauseCode<'_>, 32); +static_assert_size!(ObligationCauseCode<'_>, 40); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { @@ -398,7 +401,7 @@ ty::error::TypeError<'tcx>, ), TraitNotObjectSafe(DefId), - ConstEvalFailure(ErrorHandled), + NotConstEvaluatable(NotConstEvaluatable), Overflow, } @@ -667,6 +670,9 @@ /// Associated const. AssocConst(Symbol, Span), + + /// GAT + GAT(Symbol, Span), } impl ObjectSafetyViolation { @@ -712,6 +718,9 @@ format!("it contains associated `const` `{}`", name).into() } ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), + ObjectSafetyViolation::GAT(name, _) => { + format!("it contains the generic associated type `{}`", name).into() + } } } @@ -770,6 +779,7 @@ ); } ObjectSafetyViolation::AssocConst(name, _) + | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { err.help(&format!("consider moving `{}` to another trait", name)); } @@ -783,6 +793,7 @@ ObjectSafetyViolation::SupertraitSelf(spans) | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), ObjectSafetyViolation::AssocConst(_, span) + | ObjectSafetyViolation::GAT(_, span) | ObjectSafetyViolation::Method(_, _, span) if *span != DUMMY_SP => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/traits/query.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/traits/query.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/traits/query.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/traits/query.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,7 @@ //! which makes a canonical query by replacing unbound inference //! variables and regions, so that results can be reused more broadly. //! The providers for the queries defined here can be found in -//! `librustc_traits`. +//! `rustc_traits`. use crate::ich::StableHashingContext; use crate::infer::canonical::{Canonical, QueryResponse}; @@ -44,24 +44,12 @@ pub b: Ty<'tcx>, } - impl<'tcx> Eq<'tcx> { - pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self { - Self { a, b } - } - } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] pub struct Subtype<'tcx> { pub sub: Ty<'tcx>, pub sup: Ty<'tcx>, } - impl<'tcx> Subtype<'tcx> { - pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self { - Self { sub, sup } - } - } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] pub struct ProvePredicate<'tcx> { pub predicate: Predicate<'tcx>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/assoc.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/assoc.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/assoc.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/assoc.rs 2021-06-17 03:53:50.000000000 +0000 @@ -96,15 +96,15 @@ /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is /// done only on items with the same name. #[derive(Debug, Clone, PartialEq, HashStable)] -pub struct AssociatedItems<'tcx> { +pub struct AssocItems<'tcx> { pub(super) items: SortedIndexMultiMap, } -impl<'tcx> AssociatedItems<'tcx> { +impl<'tcx> AssocItems<'tcx> { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. pub fn new(items_in_def_order: impl IntoIterator) -> Self { let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); - AssociatedItems { items } + AssocItems { items } } /// Returns a slice of associated items in the order they were defined. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/closure.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/closure.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/closure.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/closure.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::LangItem; use rustc_span::Span; use super::{Ty, TyCtxt}; @@ -113,14 +112,6 @@ // This is the initial value used when doing upvar inference. pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn; - pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId { - match *self { - ClosureKind::Fn => tcx.require_lang_item(LangItem::Fn, None), - ClosureKind::FnMut => tcx.require_lang_item(LangItem::FnMut, None), - ClosureKind::FnOnce => tcx.require_lang_item(LangItem::FnOnce, None), - } - } - /// Returns `true` if a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { @@ -169,7 +160,7 @@ } } - /// Returns the `LocalDefId` of the closure that captureed this Place + /// Returns the `LocalDefId` of the closure that captured this Place pub fn get_closure_local_def_id(&self) -> LocalDefId { match self.place.base { HirPlaceBase::Upvar(upvar_id) => upvar_id.closure_expr_id, @@ -377,12 +368,4 @@ UniqueImmBorrow => hir::Mutability::Mut, } } - - pub fn to_user_str(&self) -> &'static str { - match *self { - MutBorrow => "mutable", - ImmBorrow => "immutable", - UniqueImmBorrow => "uniquely immutable", - } - } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/codec.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/codec.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/codec.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/codec.rs 2021-06-17 03:53:50.000000000 +0000 @@ -120,8 +120,9 @@ } } -impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands) } } @@ -188,7 +189,7 @@ } #[inline] -pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( +fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx T, D::Error> where @@ -198,7 +199,7 @@ } #[inline] -pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( +fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx [T], D::Error> where @@ -226,18 +227,22 @@ } } -impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder> { - fn decode(decoder: &mut D) -> Result>, D::Error> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { + fn decode(decoder: &mut D) -> Result>, D::Error> { + let bound_vars = Decodable::decode(decoder)?; // Handle shorthands first, if we have an usize > 0x80. - Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; - assert!(pos >= SHORTHAND_OFFSET); - let shorthand = pos - SHORTHAND_OFFSET; - - decoder.with_position(shorthand, ty::PredicateKind::decode)? - } else { - ty::PredicateKind::decode(decoder)? - })) + Ok(ty::Binder::bind_with_vars( + if decoder.positioned_at_shorthand() { + let pos = decoder.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let shorthand = pos - SHORTHAND_OFFSET; + + decoder.with_position(shorthand, ty::PredicateKind::decode)? + } else { + ty::PredicateKind::decode(decoder)? + }, + bound_vars, + )) } } @@ -319,7 +324,7 @@ } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> - for ty::List>> + for ty::List>> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; @@ -379,15 +384,23 @@ } } +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()?; + Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?) + } +} + impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx Allocation, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::List } #[macro_export] @@ -472,6 +485,11 @@ read_str -> Cow<'_, str>; } + #[inline] + fn read_raw_bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.opaque.read_raw_bytes_into(bytes) + } + fn error(&mut self, err: &str) -> Self::Error { self.opaque.error(err) } @@ -483,14 +501,16 @@ macro_rules! impl_binder_encode_decode { ($($t:ty),+ $(,)?) => { $( - impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<$t> { + impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, $t> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; self.as_ref().skip_binder().encode(e) } } - impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<$t> { + impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, $t> { fn decode(decoder: &mut D) -> Result { - Ok(ty::Binder::bind(Decodable::decode(decoder)?)) + let bound_vars = Decodable::decode(decoder)?; + Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars)) } } )* diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/consts/kind.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/consts/kind.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/consts/kind.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/consts/kind.rs 2021-06-17 03:53:50.000000000 +0000 @@ -12,10 +12,18 @@ use rustc_target::abi::Size; use super::ScalarInt; +/// An unevaluated, potentially generic, constant. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] +pub struct Unevaluated<'tcx> { + pub def: ty::WithOptConstParam, + pub substs: SubstsRef<'tcx>, + pub promoted: Option, +} /// Represents a constant in Rust. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -#[derive(HashStable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ty::ParamConst), @@ -31,7 +39,7 @@ /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(ty::WithOptConstParam, SubstsRef<'tcx>, Option), + Unevaluated(Unevaluated<'tcx>), /// Used to hold computed value. Value(ConstValue<'tcx>), @@ -102,7 +110,7 @@ tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option, ErrorReported>> { - if let ConstKind::Unevaluated(def, substs, promoted) = self { + if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self { use crate::mir::interpret::ErrorHandled; // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` @@ -132,7 +140,8 @@ let (param_env, substs) = param_env_and_substs.into_parts(); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - match tcx.const_eval_resolve(param_env, def, substs, promoted, None) { + match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None) + { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/consts.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/consts.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/consts.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/consts.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,7 +5,7 @@ use crate::ty::{ParamEnv, ParamEnvAnd}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; mod int; @@ -98,18 +98,18 @@ let name = tcx.hir().name(hir_id); ty::ConstKind::Param(ty::ParamConst::new(index, name)) } - _ => ty::ConstKind::Unevaluated( - def.to_global(), - InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - None, - ), + _ => ty::ConstKind::Unevaluated(ty::Unevaluated { + def: def.to_global(), + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), + promoted: None, + }), }; tcx.mk_const(ty::Const { val, ty }) } - #[inline] /// Interns the given value as a constant. + #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) } @@ -202,3 +202,18 @@ .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } } + +pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let default_def_id = match tcx.hir().get(hir_id) { + hir::Node::GenericParam(hir::GenericParam { + kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, + .. + }) => tcx.hir().local_def_id(ac.hir_id), + _ => span_bug!( + tcx.def_span(def_id), + "`const_param_default` expected a generic parameter with a constant" + ), + }; + Const::from_anon_const(tcx, default_def_id) +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/context.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/context.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/context.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/context.rs 2021-06-17 03:53:50.000000000 +0000 @@ -20,8 +20,8 @@ use crate::ty::{ self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst, - InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, - PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, + InferTy, IntTy, IntVar, IntVid, List, MainDefinition, ParamConst, ParamTy, PolyFnSig, + Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use rustc_ast as ast; @@ -87,7 +87,8 @@ substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, - poly_existential_predicates: InternedSet<'tcx, List>>>, + poly_existential_predicates: + InternedSet<'tcx, List>>>, predicate: InternedSet<'tcx, PredicateInner<'tcx>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, @@ -95,6 +96,7 @@ const_: InternedSet<'tcx, Const<'tcx>>, /// Const allocations. allocation: InternedSet<'tcx, Allocation>, + bound_variable_kinds: InternedSet<'tcx, List>, } impl<'tcx> CtxtInterners<'tcx> { @@ -113,6 +115,7 @@ place_elems: Default::default(), const_: Default::default(), allocation: Default::default(), + bound_variable_kinds: Default::default(), } } @@ -136,7 +139,10 @@ } #[inline(never)] - fn intern_predicate(&self, kind: Binder>) -> &'tcx PredicateInner<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + ) -> &'tcx PredicateInner<'tcx> { self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); @@ -449,7 +455,7 @@ /// Stores the type, expression, span and optional scope span of all types /// that are live across the yield of this generator (if a generator). - pub generator_interior_types: ty::Binder>>, + pub generator_interior_types: ty::Binder<'tcx, Vec>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) /// as `&[u8]`, depending on the pattern in which they are used. @@ -789,7 +795,7 @@ return false; } - user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { + iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { GenericArgKind::Type(ty) => match ty.kind() { ty::Bound(debruijn, b) => { @@ -804,7 +810,7 @@ ty::ReLateBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(*debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() + cvar == br.var } _ => false, }, @@ -1019,6 +1025,8 @@ layout_interner: ShardedHashMap<&'tcx Layout, ()>, output_filenames: Arc, + + pub main_def: Option, } impl<'tcx> TyCtxt<'tcx> { @@ -1179,6 +1187,7 @@ const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames.clone()), + main_def: resolutions.main_def, } } @@ -1616,10 +1625,11 @@ nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} -nop_list_lift! {poly_existential_predicates; ty::Binder> => ty::Binder>} +nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} +nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} @@ -1965,8 +1975,8 @@ } } -impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Binder> { +impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { + fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } @@ -2072,10 +2082,11 @@ substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: - _intern_poly_existential_predicates(ty::Binder>), + _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>), predicates: _intern_predicates(Predicate<'tcx>), projs: _intern_projs(ProjectionKind), place_elems: _intern_place_elems(PlaceElem<'tcx>), + bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind), ); impl<'tcx> TyCtxt<'tcx> { @@ -2158,7 +2169,7 @@ } #[inline] - pub fn mk_predicate(self, binder: Binder>) -> Predicate<'tcx> { + pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { let inner = self.interners.intern_predicate(binder); Predicate { inner } } @@ -2167,7 +2178,7 @@ pub fn reuse_or_mk_predicate( self, pred: Predicate<'tcx>, - binder: Binder>, + binder: Binder<'tcx, PredicateKind<'tcx>>, ) -> Predicate<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } @@ -2221,7 +2232,7 @@ let adt_def = self.adt_def(wrapper_def_id); let substs = InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => bug!(), + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), GenericParamDefKind::Type { has_default, .. } => { if param.index == 0 { ty_param.into() @@ -2289,11 +2300,6 @@ } #[inline] - pub fn mk_nil_ptr(self) -> Ty<'tcx> { - self.mk_imm_ptr(self.mk_unit()) - } - - #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) } @@ -2339,7 +2345,7 @@ #[inline] pub fn mk_dynamic( self, - obj: &'tcx List>>, + obj: &'tcx List>>, reg: ty::Region<'tcx>, ) -> Ty<'tcx> { self.mk_ty(Dynamic(obj, reg)) @@ -2366,7 +2372,7 @@ } #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { + pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List>>) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types)) } @@ -2416,7 +2422,7 @@ self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() } } @@ -2471,8 +2477,8 @@ pub fn intern_poly_existential_predicates( self, - eps: &[ty::Binder>], - ) -> &'tcx List>> { + eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + ) -> &'tcx List>> { assert!(!eps.is_empty()); assert!( eps.array_windows() @@ -2517,6 +2523,13 @@ if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) } } + pub fn intern_bound_variable_kinds( + self, + ts: &[ty::BoundVariableKind], + ) -> &'tcx List { + if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) } + } + pub fn mk_fn_sig( self, inputs: I, @@ -2538,8 +2551,8 @@ pub fn mk_poly_existential_predicates< I: InternAs< - [ty::Binder>], - &'tcx List>>, + [ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + &'tcx List>>, >, >( self, @@ -2577,6 +2590,15 @@ self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) } + pub fn mk_bound_variable_kinds< + I: InternAs<[ty::BoundVariableKind], &'tcx List>, + >( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) + } + /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { @@ -2641,6 +2663,7 @@ } pub fn named_region(self, id: HirId) -> Option { + debug!(?id, "named_region"); self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) } @@ -2649,9 +2672,19 @@ .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) } - pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { + pub fn object_lifetime_defaults(self, id: HirId) -> Option> { self.object_lifetime_defaults_map(id.owner) - .and_then(|map| map.get(&id.local_id).map(|v| &**v)) + } + + pub fn late_bound_vars(self, id: HirId) -> &'tcx List { + self.mk_bound_variable_kinds( + self.late_bound_vars_map(id.owner) + .and_then(|map| map.get(&id.local_id).cloned()) + .unwrap_or_else(|| { + bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) + }) + .iter(), + ) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/erase_regions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/erase_regions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/erase_regions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/erase_regions.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,4 @@ +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::{self, Ty, TyCtxt, TypeFlags}; @@ -43,7 +44,7 @@ if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -65,4 +66,8 @@ _ => self.tcx.lifetimes.re_erased, } } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/error.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/error.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/error.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/error.rs 2021-06-17 03:53:50.000000000 +0000 @@ -36,6 +36,7 @@ UnsafetyMismatch(ExpectedFound), AbiMismatch(ExpectedFound), Mutability, + ArgumentMutability(usize), TupleSize(ExpectedFound), FixedArraySize(ExpectedFound), ArgCount, @@ -46,6 +47,7 @@ RegionsPlaceholderMismatch, Sorts(ExpectedFound>), + ArgumentSorts(ExpectedFound>, usize), IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), Traits(ExpectedFound), @@ -57,7 +59,9 @@ CyclicTy(Ty<'tcx>), CyclicConst(&'tcx ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), - ExistentialMismatch(ExpectedFound<&'tcx ty::List>>>), + ExistentialMismatch( + ExpectedFound<&'tcx ty::List>>>, + ), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), @@ -108,7 +112,7 @@ AbiMismatch(values) => { write!(f, "expected {} fn, found {} fn", values.expected, values.found) } - Mutability => write!(f, "types differ in mutability"), + ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"), TupleSize(values) => write!( f, "expected a tuple with {} element{}, \ @@ -140,7 +144,7 @@ br_string(br) ), RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"), - Sorts(values) => ty::tls::with(|tcx| { + ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| { report_maybe_different( f, &values.expected.sort_string(tcx), @@ -197,10 +201,11 @@ use self::TypeError::*; match self { CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_) - | FixedArraySize(_) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) - | VariadicMismatch(_) | TargetFeatureCast(_) => false, + | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) + | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false, Mutability + | ArgumentMutability(_) | TupleSize(_) | ArgCount | RegionsDoesNotOutlive(..) @@ -337,7 +342,7 @@ use self::TypeError::*; debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause); match err { - Sorts(values) => { + ArgumentSorts(values, _) | Sorts(values) => { match (values.expected.kind(), values.found.kind()) { (ty::Closure(..), ty::Closure(..)) => { db.note("no two closures, even if identical, have the same type"); @@ -509,13 +514,18 @@ "consider constraining the associated type `{}` to `{}`", values.found, values.expected, ); - if !self.suggest_constraint( + if !(self.suggest_constraining_opaque_associated_type( + db, + &msg, + proj_ty, + values.expected, + ) || self.suggest_constraint( db, &msg, body_owner_def_id, proj_ty, values.expected, - ) { + )) { db.help(&msg); db.note( "for more information, visit \ @@ -699,20 +709,7 @@ } } - if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { - // When the expected `impl Trait` is not defined in the current item, it will come from - // a return type. This can occur when dealing with `TryStream` (#71035). - if self.constrain_associated_type_structured_suggestion( - db, - self.def_span(def_id), - &assoc, - proj_ty.trait_ref_and_own_substs(self).1, - values.found, - &msg, - ) { - return; - } - } + self.suggest_constraining_opaque_associated_type(db, &msg, proj_ty, values.found); if self.point_at_associated_type(db, body_owner_def_id, values.found) { return; @@ -750,6 +747,30 @@ } } + /// When the expected `impl Trait` is not defined in the current item, it will come from + /// a return type. This can occur when dealing with `TryStream` (#71035). + fn suggest_constraining_opaque_associated_type( + self, + db: &mut DiagnosticBuilder<'_>, + msg: &str, + proj_ty: &ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let assoc = self.associated_item(proj_ty.item_def_id); + if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { + self.constrain_associated_type_structured_suggestion( + db, + self.def_span(def_id), + &assoc, + proj_ty.trait_ref_and_own_substs(self).1, + ty, + &msg, + ) + } else { + false + } + } + fn point_at_methods_that_satisfy_associated_type( self, db: &mut DiagnosticBuilder<'_>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/flags.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/flags.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/flags.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/flags.rs 2021-06-17 03:53:50.000000000 +0000 @@ -22,7 +22,7 @@ result } - pub fn for_predicate(binder: ty::Binder>) -> FlagComputation { + pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -53,12 +53,16 @@ /// Adds the flags/depth from a set of types that appear within the current type, but within a /// region binder. - fn bound_computation(&mut self, value: ty::Binder, f: F) + fn bound_computation(&mut self, value: ty::Binder<'_, T>, f: F) where F: FnOnce(&mut Self, T), { let mut computation = FlagComputation::new(); + if !value.bound_vars().is_empty() { + computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; + } + f(&mut computation, value.skip_binder()); self.add_flags(computation.flags); @@ -204,7 +208,7 @@ } } - fn add_predicate(&mut self, binder: ty::Binder>) { + fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); } @@ -270,10 +274,7 @@ fn add_const(&mut self, c: &ty::Const<'_>) { self.add_ty(c.ty); match c.val { - ty::ConstKind::Unevaluated(_, substs, _) => { - self.add_substs(substs); - self.add_flags(TypeFlags::HAS_CT_PROJECTION); - } + ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated), ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { @@ -297,6 +298,11 @@ } } + fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { + self.add_substs(ct.substs); + self.add_flags(TypeFlags::HAS_CT_PROJECTION); + } + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); self.add_ty(projection.ty); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/fold.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/fold.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/fold.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/fold.rs 2021-06-17 03:53:50.000000000 +0000 @@ -30,11 +30,13 @@ //! //! These methods return true to indicate that the visitor has found what it is //! looking for, and does not need to visit anything else. +use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sso::SsoHashSet; use std::collections::BTreeMap; use std::fmt; use std::ops::ControlFlow; @@ -42,7 +44,7 @@ /// This trait is implemented for every type that can be folded. /// Basically, every type that has a corresponding method in `TypeFolder`. /// -/// To implement this conveniently, use the derive macro located in librustc_macros. +/// 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 { @@ -161,7 +163,7 @@ pub trait TypeFolder<'tcx>: Sized { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - fn fold_binder(&mut self, t: Binder) -> Binder + fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -179,12 +181,19 @@ fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { c.super_fold_with(self) } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + bug!("most type folders should not be folding MIR datastructures: {:?}", c) + } } pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { t.super_visit_with(self) } @@ -322,7 +331,7 @@ fn visit_binder>( &mut self, - t: &Binder, + t: &Binder<'tcx, T>, ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.as_ref().skip_binder().visit_with(self); @@ -400,7 +409,10 @@ self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -460,7 +472,10 @@ self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -538,7 +553,7 @@ /// contain escaping bound types. pub fn replace_late_bound_regions( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, ) -> (T, BTreeMap>) where @@ -588,7 +603,7 @@ /// types. pub fn replace_bound_vars( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, fld_t: G, fld_c: H, @@ -607,7 +622,11 @@ /// Replaces any late-bound regions bound in `value` with /// free variants attached to `all_outlive_scope`. - pub fn liberate_late_bound_regions(self, all_outlive_scope: DefId, value: ty::Binder) -> T + pub fn liberate_late_bound_regions( + self, + all_outlive_scope: DefId, + value: ty::Binder<'tcx, T>, + ) -> T where T: TypeFoldable<'tcx>, { @@ -620,13 +639,49 @@ .0 } + pub fn shift_bound_var_indices(self, bound_vars: usize, value: T) -> T + where + T: TypeFoldable<'tcx>, + { + self.replace_escaping_bound_vars( + value, + |r| { + self.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars), + kind: r.kind, + }, + )) + }, + |t| { + self.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars), + kind: t.kind, + }, + )) + }, + |c, ty| { + self.mk_const(ty::Const { + val: ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(c.as_usize() + bound_vars), + ), + ty, + }) + }, + ) + } + /// Returns a set of all late-bound regions that are constrained /// by `value`, meaning that if we instantiate those LBR with /// variables and equate `value` with something else, those /// variables will also be equated. pub fn collect_constrained_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -637,7 +692,7 @@ /// Returns a set of all late-bound regions that appear in `value` anywhere. pub fn collect_referenced_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -647,7 +702,7 @@ fn collect_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, just_constraint: bool, ) -> FxHashSet where @@ -661,7 +716,7 @@ /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. - pub fn erase_late_bound_regions(self, value: Binder) -> T + pub fn erase_late_bound_regions(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { @@ -676,20 +731,205 @@ /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. - pub fn anonymize_late_bound_regions(self, sig: Binder) -> Binder + pub fn anonymize_late_bound_regions(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { let mut counter = 0; - Binder::bind( - self.replace_late_bound_regions(sig, |_| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let inner = self + .replace_late_bound_regions(sig, |_| { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; r }) - .0, - ) + .0; + let bound_vars = self.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + Binder::bind_with_vars(inner, bound_vars) + } +} + +pub struct BoundVarsCollector<'tcx> { + binder_index: ty::DebruijnIndex, + vars: BTreeMap, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> BoundVarsCollector<'tcx> { + pub fn new() -> Self { + BoundVarsCollector { + binder_index: ty::INNERMOST, + vars: BTreeMap::new(), + visited: SsoHashSet::default(), + } + } + + pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { + let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0); + for i in 0..max { + if let None = self.vars.get(&i) { + panic!("Unknown variable: {:?}", i); + } + } + + tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) + } +} + +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::CONTINUE; + } + use std::collections::btree_map::Entry; + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + match self.vars.entry(bound_ty.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Ty(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, _br) if *index == self.binder_index => { + // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind` + bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br) + } + + _ => (), + }; + + r.super_visit_with(self) + } +} + +pub struct ValidateBoundVars<'tcx> { + bound_vars: &'tcx ty::List, + binder_index: ty::DebruijnIndex, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> ValidateBoundVars<'tcx> { + pub fn new(bound_vars: &'tcx ty::List) -> Self { + ValidateBoundVars { + bound_vars, + binder_index: ty::INNERMOST, + visited: SsoHashSet::default(), + } + } +} + +impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::BREAK; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + if self.bound_vars.len() <= bound_ty.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars); + } + let list_var = self.bound_vars[bound_ty.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Ty(kind) => { + if kind != bound_ty.kind { + bug!( + "Mismatched type kinds: {:?} doesn't var in list {:?}", + bound_ty.kind, + list_var + ); + } + } + _ => { + bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var) + } + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => { + if self.bound_vars.len() <= br.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars); + } + let list_var = self.bound_vars[br.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Region(kind) => { + if kind != br.kind { + bug!( + "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})", + br.kind, + list_var, + self.bound_vars + ); + } + } + _ => bug!( + "Mismatched bound variable kinds! Expected region, found {:?}", + list_var + ), + } + } + + _ => (), + }; + + r.super_visit_with(self) } } @@ -719,7 +959,10 @@ self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -828,7 +1071,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); @@ -974,7 +1220,10 @@ } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.current_index.shift_in(1); let result = t.super_visit_with(self); self.current_index.shift_out(1); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/generics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/generics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/generics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/generics.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,7 +18,9 @@ object_lifetime_default: ObjectLifetimeDefault, synthetic: Option, }, - Const, + Const { + has_default: bool, + }, } impl GenericParamDefKind { @@ -26,15 +28,15 @@ match self { GenericParamDefKind::Lifetime => "lifetime", GenericParamDefKind::Type { .. } => "type", - GenericParamDefKind::Const => "constant", + GenericParamDefKind::Const { .. } => "constant", } } pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { match self { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + GenericParamDefKind::Const { .. } => { + ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } } } } @@ -105,7 +107,7 @@ match param.kind { GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, GenericParamDefKind::Type { .. } => own_counts.types += 1, - GenericParamDefKind::Const => own_counts.consts += 1, + GenericParamDefKind::Const { .. } => own_counts.consts += 1, } } @@ -121,8 +123,8 @@ GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } - GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) + GenericParamDefKind::Const { has_default } => { + own_defaults.consts += has_default as usize; } } } @@ -146,7 +148,9 @@ pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + return true; + } GenericParamDefKind::Lifetime => {} } } @@ -189,7 +193,7 @@ pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { - GenericParamDefKind::Const => param, + GenericParamDefKind::Const { .. } => param, _ => bug!("expected const parameter, but found another generic parameter"), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/instance.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/instance.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/instance.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/instance.rs 2021-06-17 03:53:50.000000000 +0000 @@ -216,9 +216,10 @@ // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. return ty.ty_adt_def().map_or(true, |adt_def| { - adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| { - tcx.codegen_fn_attrs(dtor.did).requests_inline() - }) + adt_def.destructor(tcx).map_or_else( + || adt_def.is_enum(), + |dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(), + ) }); } tcx.codegen_fn_attrs(self.def_id()).requests_inline() @@ -482,6 +483,7 @@ if let Some(substs) = self.substs_for_mir_body() { v.subst(tcx, substs) } else { *v } } + #[inline(always)] pub fn subst_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, @@ -593,7 +595,7 @@ }, // Simple case: If parameter is a const or type parameter.. - ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if + ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if // ..and is within range and unused.. unused.contains(param.index).unwrap_or(false) => // ..then use the identity for this parameter. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/layout.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/layout.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/layout.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/layout.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use crate::ich::StableHashingContext; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; @@ -11,7 +12,7 @@ use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ @@ -1251,13 +1252,13 @@ } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; - for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) { + for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { let offsets = match layout_variant.fields { FieldsShape::Arbitrary { ref offsets, .. } => offsets, _ => bug!(), }; let mut fields = - field_layouts.iter().zip(offsets).filter(|p| !p.0.is_zst()); + iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { (None, None) => continue, (Some(pair), None) => pair, @@ -1626,7 +1627,7 @@ const INVALID_FIELD_IDX: u32 = !0; let mut combined_inverse_memory_index = vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()]; - let mut offsets_and_memory_index = offsets.into_iter().zip(memory_index); + let mut offsets_and_memory_index = iter::zip(offsets, memory_index); let combined_offsets = variant_fields .iter() .enumerate() @@ -2318,31 +2319,30 @@ ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let address_space = addr_space_of_ty(ty); let tcx = cx.tcx(); - let is_freeze = ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()); - let kind = match mt { - hir::Mutability::Not => { - if is_freeze { - PointerKind::Frozen - } else { - PointerKind::Shared + let kind = if tcx.sess.opts.optimize == OptLevel::No { + // Use conservative pointer kind if not optimizing. This saves us the + // Freeze/Unpin queries, and can save time in the codegen backend (noalias + // attributes in LLVM have compile-time cost even in unoptimized builds). + PointerKind::Shared + } else { + match mt { + hir::Mutability::Not => { + if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::Frozen + } else { + PointerKind::Shared + } } - } - hir::Mutability::Mut => { - // Previously we would only emit noalias annotations for LLVM >= 6 or in - // panic=abort mode. That was deemed right, as prior versions had many bugs - // in conjunction with unwinding, but later versions didn’t seem to have - // said issues. See issue #31681. - // - // Alas, later on we encountered a case where noalias would generate wrong - // code altogether even with recent versions of LLVM in *safe* code with no - // unwinding involved. See #54462. - // - // For now, do not enable mutable_noalias by default at all, while the - // issue is being figured out. - if tcx.sess.opts.debugging_opts.mutable_noalias { - PointerKind::UniqueBorrowed - } else { - PointerKind::Shared + hir::Mutability::Mut => { + // References to self-referential structures should not be considered + // noalias, as another pointer to the structure can be obtained, that + // is not based-on the original reference. We consider all !Unpin + // types to be potentially self-referential here. + if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::UniqueBorrowed + } else { + PointerKind::Shared + } } } }; @@ -2482,21 +2482,42 @@ ty::Closure(def_id, substs) => { let sig = substs.as_closure().sig(); - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| { + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + let sig = sig.skip_binder(); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( - iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, sig.unsafety, sig.abi, - ) - }) + ), + bound_vars, + ) } ty::Generator(_, substs, _) => { let sig = substs.as_generator().poly_sig(); - let br = ty::BoundRegion { kind: ty::BrEnv }; + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; let env_region = ty::ReLateBound(ty::INNERMOST, br); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); @@ -2505,21 +2526,21 @@ let pin_substs = tcx.intern_substs(&[env_ty.into()]); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - sig.map_bound(|sig| { - let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = - tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - + let sig = sig.skip_binder(); + let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( [env_ty, sig.resume_ty].iter(), &ret_ty, false, hir::Unsafety::Normal, rustc_target::spec::abi::Abi::Rust, - ) - }) + ), + bound_vars, + ) } _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), } @@ -2609,6 +2630,7 @@ | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => false, @@ -2691,6 +2713,7 @@ AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, + Wasm => Conv::C, // These API constants ought to be more specific... Cdecl => Conv::C, @@ -2775,10 +2798,14 @@ // and can be marked as both `readonly` and `noalias`, as // LLVM's definition of `noalias` is based solely on memory // dependencies rather than pointer equality + // + // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute + // for UniqueBorrowed arguments, so that the codegen backend can decide + // whether or not to actually emit the attribute. let no_alias = match kind { - PointerKind::Shared => false, + PointerKind::Shared | PointerKind::UniqueBorrowed => false, PointerKind::UniqueOwned => true, - PointerKind::Frozen | PointerKind::UniqueBorrowed => !is_return, + PointerKind::Frozen => !is_return, }; if no_alias { attrs.set(ArgAttribute::NoAlias); @@ -2787,6 +2814,10 @@ if kind == PointerKind::Frozen && !is_return { attrs.set(ArgAttribute::ReadOnly); } + + if kind == PointerKind::UniqueBorrowed && !is_return { + attrs.set(ArgAttribute::NoAliasMutRef); + } } } }; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/_match.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/_match.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/_match.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/_match.rs 2021-06-17 03:53:50.000000000 +0000 @@ -112,9 +112,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -55,7 +55,7 @@ pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; -pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, ValTree}; +pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree}; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, @@ -67,12 +67,12 @@ pub use self::sty::RegionKind::*; pub use self::sty::TyKind::*; pub use self::sty::{ - Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig, - ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, - GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, - PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, - TyKind, TypeAndMut, UpvarSubsts, + Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, + CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, + ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, + GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, + PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, + RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, }; pub use self::trait_def::TraitDef; @@ -124,6 +124,20 @@ /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. pub extern_prelude: FxHashMap, + pub main_def: Option, +} + +#[derive(Clone, Copy)] +pub struct MainDefinition { + pub res: Res, + pub is_import: bool, + pub span: Span, +} + +impl MainDefinition { + pub fn opt_fn_def_id(self) -> Option { + if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } + } } /// The "header" of an impl is everything outside the body: a Self type, a trait @@ -302,7 +316,7 @@ // `TyS` 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!(TyS<'_>, 32); +static_assert_size!(TyS<'_>, 40); impl<'tcx> Ord for TyS<'tcx> { fn cmp(&self, other: &TyS<'tcx>) -> Ordering { @@ -359,14 +373,14 @@ #[derive(Debug)] crate struct PredicateInner<'tcx> { - kind: Binder>, + kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, /// See the comment for the corresponding field of [TyS]. outer_exclusive_binder: ty::DebruijnIndex, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 40); +static_assert_size!(PredicateInner<'_>, 48); #[derive(Clone, Copy, Lift)] pub struct Predicate<'tcx> { @@ -389,9 +403,9 @@ impl<'tcx> Eq for Predicate<'tcx> {} impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder>`. + /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] - pub fn kind(self) -> Binder> { + pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { self.inner.kind } } @@ -543,10 +557,33 @@ // substitution code expects equal binding levels in the values // from the substitution and the value being substituted into, and // this trick achieves that). - let substs = trait_ref.skip_binder().substs; - let pred = self.kind().skip_binder(); - let new = pred.subst(tcx, substs); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new)) + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait substs to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars)); + tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) } } @@ -556,7 +593,7 @@ pub trait_ref: TraitRef<'tcx>, } -pub type PolyTraitPredicate<'tcx> = ty::Binder>; +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { pub fn def_id(self) -> DefId { @@ -574,7 +611,7 @@ self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder> { + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound(|trait_ref| trait_ref.self_ty()) } } @@ -584,8 +621,8 @@ pub struct OutlivesPredicate(pub A, pub B); // `A: B` pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] @@ -594,7 +631,7 @@ pub a: Ty<'tcx>, pub b: Ty<'tcx>, } -pub type PolySubtypePredicate<'tcx> = ty::Binder>; +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: @@ -615,25 +652,15 @@ pub ty: Ty<'tcx>, } -pub type PolyProjectionPredicate<'tcx> = Binder>; +pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { - /// Returns the `DefId` of the associated item being projected. - pub fn item_def_id(&self) -> DefId { - self.skip_binder().projection_ty.item_def_id - } - /// Returns the `DefId` of the trait of the associated item being projected. #[inline] pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { self.skip_binder().projection_ty.trait_def_id(tcx) } - #[inline] - pub fn projection_self_ty(&self) -> Binder> { - self.map_bound(|predicate| predicate.projection_ty.self_ty()) - } - /// Get the [PolyTraitRef] required for this projection to be well formed. /// Note that for generic associated types the predicates of the associated /// type also need to be checked. @@ -647,7 +674,7 @@ self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } - pub fn ty(&self) -> Binder> { + pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound(|predicate| predicate.ty) } @@ -681,7 +708,7 @@ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } -impl ToPredicate<'tcx> for Binder> { +impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) @@ -704,11 +731,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ConstnessAnd { - value: self.value.map_bound(|trait_ref| ty::TraitPredicate { trait_ref }), - constness: self.constness, - } - .to_predicate(tcx) + self.value + .map_bound(|trait_ref| { + PredicateKind::Trait(ty::TraitPredicate { trait_ref }, self.constness) + }) + .to_predicate(tcx) } } @@ -1039,10 +1066,6 @@ None } - pub fn expect_local(self) -> WithOptConstParam { - self.as_local().unwrap() - } - pub fn is_local(self) -> bool { self.did.is_local() } @@ -1949,6 +1972,7 @@ trait_impls_of: trait_def::trait_impls_of_provider, all_local_trait_impls: trait_def::all_local_trait_impls, type_uninhabited_from: inhabitedness::type_uninhabited_from, + const_param_default: consts::const_param_default, ..*providers }; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs 2021-06-17 03:53:50.000000000 +0000 @@ -7,6 +7,7 @@ //! `normalize_generic_arg_after_erasing_regions` query for each type //! or constant found within. (This underlying query is what is cached.) +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; @@ -38,7 +39,7 @@ } } - /// If you have a `Binder`, you can do this to strip out the + /// 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 /// binder is being instantiated at the call site. @@ -49,7 +50,7 @@ pub fn normalize_erasing_late_bound_regions( self, param_env: ty::ParamEnv<'tcx>, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable<'tcx>, @@ -101,4 +102,10 @@ let arg = self.param_env.and(c.into()); self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() } + + #[inline] + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + let arg = self.param_env.and(c); + self.tcx.normalize_mir_const_after_erasing_regions(arg) + } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/print/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/print/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/print/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/print/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -63,7 +63,7 @@ fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result; fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result; @@ -193,17 +193,19 @@ .params .iter() .rev() - .take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default - && substs[param.index as usize] - == GenericArg::from( - self.tcx().type_of(param.def_id).subst(self.tcx(), substs), - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults) + .take_while(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default + && substs[param.index as usize] + == GenericArg::from( + self.tcx().type_of(param.def_id).subst(self.tcx(), substs), + ) + } + ty::GenericParamDefKind::Const { has_default } => { + has_default + && substs[param.index as usize] + == GenericArg::from(self.tcx().const_param_default(param.def_id)) } }) .count(); @@ -344,7 +346,7 @@ } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> - for &'tcx ty::List>> + for &'tcx ty::List>> { type Output = P::DynExistential; type Error = P::Error; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/print/pretty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/print/pretty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/print/pretty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/print/pretty.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,6 +4,7 @@ use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -19,6 +20,7 @@ use std::collections::BTreeMap; use std::convert::TryFrom; use std::fmt::{self, Write as _}; +use std::iter; use std::ops::{ControlFlow, Deref, DerefMut}; // `pretty` is a separate module only for organization. @@ -201,7 +203,7 @@ self.print_def_path(def_id, substs) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -210,7 +212,7 @@ fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: F, ) -> Result where @@ -764,7 +766,7 @@ fn pretty_print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -915,7 +917,7 @@ } match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { if let Some(promoted) = promoted { p!(print_value_path(def.did, substs)); p!(write("::{:?}", promoted)); @@ -1223,7 +1225,7 @@ CtorKind::Fictive => { p!(" {{ "); let mut first = true; - for (field_def, field) in variant_def.fields.iter().zip(fields) { + for (field_def, field) in iter::zip(&variant_def.fields, fields) { if !first { p!(", "); } @@ -1420,7 +1422,8 @@ } fn print_type(mut self, ty: Ty<'tcx>) -> Result { - if self.tcx.sess.type_length_limit().value_within_limit(self.printed_type_count) { + let type_length_limit = self.tcx.sess.type_length_limit(); + if type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) } else { @@ -1431,7 +1434,7 @@ fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { self.pretty_print_dyn_existential(predicates) } @@ -1570,7 +1573,7 @@ Ok(self) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -1579,7 +1582,7 @@ fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1635,7 +1638,7 @@ data.name != kw::Empty && data.name != kw::UnderscoreLifetime } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1714,7 +1717,7 @@ return Ok(self); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1762,7 +1765,7 @@ impl FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, @@ -1801,35 +1804,101 @@ define_scoped_cx!(self); let mut region_index = self.region_index; - let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { - let _ = start_or_continue(&mut self, "for<", ", "); - let kind = match br.kind { - ty::BrNamed(_, name) => { - let _ = write!(self, "{}", name); - br.kind - } - ty::BrAnon(_) | ty::BrEnv => { - let name = loop { - let name = name_by_region_index(region_index); - region_index += 1; - if !self.used_region_names.contains(&name) { - break name; - } - }; - let _ = write!(self, "{}", name); - ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + // If we want to print verbosly, then print *all* binders, even if they + // aren't named. Eventually, we might just want this as the default, but + // this is not *quite* right and changes the ordering of some output + // anyways. + let new_value = if self.tcx().sess.verbose() { + // anon index + 1 (BrEnv takes 0) -> name + let mut region_map: BTreeMap = BTreeMap::default(); + let bound_vars = value.bound_vars(); + for var in bound_vars { + match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => { + let _ = start_or_continue(&mut self, "for<", ", "); + let _ = write!(self, "{}", name); + } + ty::BoundVariableKind::Region(ty::BrAnon(i)) => { + let _ = start_or_continue(&mut self, "for<", ", "); + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(self, "{}", name); + region_map.insert(i + 1, name); + } + ty::BoundVariableKind::Region(ty::BrEnv) => { + let _ = start_or_continue(&mut self, "for<", ", "); + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(self, "{}", name); + region_map.insert(0, name); + } + _ => continue, } - }; - self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind })) - }); - start_or_continue(&mut self, "", "> ")?; + } + start_or_continue(&mut self, "", "> ")?; + + self.tcx.replace_late_bound_regions(value.clone(), |br| { + let kind = match br.kind { + ty::BrNamed(_, _) => br.kind, + ty::BrAnon(i) => { + let name = region_map[&(i + 1)]; + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + ty::BrEnv => { + let name = region_map[&0]; + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + }; + self.tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )) + }) + } else { + let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { + let _ = start_or_continue(&mut self, "for<", ", "); + let kind = match br.kind { + ty::BrNamed(_, name) => { + let _ = write!(self, "{}", name); + br.kind + } + ty::BrAnon(_) | ty::BrEnv => { + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(self, "{}", name); + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + }; + self.tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )) + }); + start_or_continue(&mut self, "", "> ")?; + new_value + }; self.binder_depth += 1; self.region_index = region_index; Ok((self, new_value)) } - pub fn pretty_in_binder(self, value: &ty::Binder) -> Result + pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1843,7 +1912,7 @@ pub fn pretty_wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1857,28 +1926,52 @@ Ok(inner) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) + fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeFoldable<'tcx>, { - struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { + debug!("prepare_late_bound_region_info(value: {:?})", value); + + struct LateBoundRegionNameCollector<'a, 'tcx> { + used_region_names: &'a mut FxHashSet, + type_collector: SsoHashSet>, + } + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { + type BreakTy = (); + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r { - self.0.insert(name); + debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); + if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { + self.used_region_names.insert(name); } r.super_visit_with(self) } + + // We collect types in order to prevent really large types from compiling for + // a really long time. See issue #83150 for why this is necessary. + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + debug!("LateBoundRegionNameCollector::visit_ty(ty: {:?}", ty); + let not_previously_inserted = self.type_collector.insert(ty); + if not_previously_inserted { + ty.super_visit_with(self) + } else { + ControlFlow::CONTINUE + } + } } self.used_region_names.clear(); - let mut collector = LateBoundRegionNameCollector(&mut self.used_region_names); + let mut collector = LateBoundRegionNameCollector { + used_region_names: &mut self.used_region_names, + type_collector: SsoHashSet::new(), + }; value.visit_with(&mut collector); self.region_index = 0; } } -impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder +impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>, { @@ -1965,28 +2058,28 @@ } } -impl ty::Binder> { - pub fn print_only_trait_path(self) -> ty::Binder> { +impl 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()) } } forward_display_to_print! { Ty<'tcx>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder, ty::Region<'tcx>>>, - ty::Binder, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, + ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, ty::FnSig<'tcx>>, + ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, + ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, ty::OutlivesPredicate, ty::Region<'tcx>>, ty::OutlivesPredicate, ty::Region<'tcx>> diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/query/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/query/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/query/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/query/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -217,8 +217,11 @@ fn default() -> Self { Providers { $($name: |_, key| bug!( - "`tcx.{}({:?})` unsupported by its crate", - stringify!($name), key + "`tcx.{}({:?})` unsupported by its crate; \ + perhaps the `{}` query was never assigned a provider function", + stringify!($name), + key, + stringify!($name), ),)* } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/query/on_disk_cache.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/query/on_disk_cache.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/query/on_disk_cache.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/query/on_disk_cache.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,7 +4,6 @@ use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; @@ -17,7 +16,7 @@ use rustc_query_system::dep_graph::DepContext; use rustc_query_system::query::QueryContext; use rustc_serialize::{ - opaque::{self, FileEncodeResult, FileEncoder}, + opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, Decodable, Decoder, Encodable, Encoder, }; use rustc_session::{CrateDisambiguator, Session}; @@ -526,7 +525,7 @@ ) { let mut current_diagnostics = self.current_diagnostics.borrow_mut(); - let x = current_diagnostics.entry(dep_node_index).or_insert(Vec::new()); + let x = current_diagnostics.entry(dep_node_index).or_default(); x.extend(Into::>::into(diagnostics)); } @@ -913,12 +912,6 @@ } } -impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable> for &'tcx FxHashSet { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result { RefDecodable::decode(d) @@ -1011,12 +1004,6 @@ } } -impl<'a, 'tcx, E: OpaqueEncoder> FingerprintEncoder for CacheEncoder<'a, 'tcx, E> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), E::Error> { - self.encoder.encode_fingerprint(f) - } -} - impl<'a, 'tcx, E> Encodable> for SyntaxContext where E: 'a + OpaqueEncoder, @@ -1167,6 +1154,7 @@ emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -1180,42 +1168,6 @@ } } -// An integer that will always encode to 8 bytes. -struct IntEncodedWithFixedSize(u64); - -impl IntEncodedWithFixedSize { - pub const ENCODED_SIZE: usize = 8; -} - -impl Encodable for IntEncodedWithFixedSize { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - let start_pos = e.position(); - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - ((self.0 >> (i * 8)) as u8).encode(e)?; - } - let end_pos = e.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(()) - } -} - -impl<'a> Decodable> for IntEncodedWithFixedSize { - fn decode(decoder: &mut opaque::Decoder<'a>) -> Result { - let mut value: u64 = 0; - let start_pos = decoder.position(); - - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - let byte: u8 = Decodable::decode(decoder)?; - value |= (byte as u64) << (i * 8); - } - - let end_pos = decoder.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - - Ok(IntEncodedWithFixedSize(value)) - } -} - pub fn encode_query_results<'a, 'tcx, CTX, Q>( tcx: CTX, encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, @@ -1233,20 +1185,27 @@ assert!(Q::query_state(tcx).all_inactive()); let cache = Q::query_cache(tcx); - cache.iter_results(|results| { - for (key, value, dep_node) in results { - if Q::cache_on_disk(tcx, &key, Some(value)) { - let dep_node = SerializedDepNodeIndex::new(dep_node.index()); - - // Record position of the cache entry. - query_result_index - .push((dep_node, AbsoluteBytePos::new(encoder.encoder.position()))); - - // Encode the type check tables with the `SerializedDepNodeIndex` - // as tag. - encoder.encode_tagged(dep_node, value)?; + let mut res = Ok(()); + cache.iter_results(&mut |key, value, dep_node| { + if res.is_err() { + return; + } + if Q::cache_on_disk(tcx, &key, Some(value)) { + let dep_node = SerializedDepNodeIndex::new(dep_node.index()); + + // Record position of the cache entry. + query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.encoder.position()))); + + // Encode the type check tables with the `SerializedDepNodeIndex` + // as tag. + match encoder.encode_tagged(dep_node, value) { + Ok(()) => {} + Err(e) => { + res = Err(e); + } } } - Ok(()) - }) + }); + + res } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/relate.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/relate.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/relate.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/relate.rs 2021-06-17 03:53:50.000000000 +0000 @@ -33,15 +33,6 @@ /// relation. Just affects error messages. fn a_is_expected(&self) -> bool; - /// Whether we should look into the substs of unevaluated constants - /// even if `feature(const_evaluatable_checked)` is active. - /// - /// This is needed in `combine` to prevent accidentially creating - /// infinite types as we abuse `TypeRelation` to walk a type there. - fn visit_ct_substs(&self) -> bool { - false - } - fn with_cause(&mut self, _cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -102,9 +93,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>; } @@ -149,7 +140,7 @@ ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); - let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { + 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, a, b) }); @@ -179,12 +170,8 @@ return Err(TypeError::ArgCount); } - let inputs_and_output = a - .inputs() - .iter() - .cloned() - .zip(b.inputs().iter().cloned()) - .map(|x| (x, false)) + let inputs_and_output = iter::zip(a.inputs(), b.inputs()) + .map(|(&a, &b)| ((a, b), false)) .chain(iter::once(((a.output(), b.output()), true))) .map(|((a, b), is_output)| { if is_output { @@ -192,6 +179,12 @@ } else { relation.relate_with_variance(ty::Contravariant, a, b) } + }) + .enumerate() + .map(|(i, r)| match r { + Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)), + Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)), + r => r, }); Ok(ty::FnSig { inputs_and_output: tcx.mk_type_list(inputs_and_output)?, @@ -308,7 +301,7 @@ ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?; + let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -432,9 +425,9 @@ let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); match (sz_a, sz_b) { - (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - expected_found(relation, sz_a_val, sz_b_val), - )), + (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( + TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), + ), _ => Err(err), } } @@ -449,7 +442,7 @@ (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup( - as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), + iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) @@ -531,24 +524,26 @@ check_const_value_eq(relation, a_val, b_val, a, b)? } - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => { - tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if tcx.features().const_evaluatable_checked => + { + tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `const_evaluatable_checked` can // be stabilized. - ( - ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted), - ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted), - ) if a_def == b_def && a_promoted == b_promoted => { + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if au.def == bu.def && au.promoted == bu.promoted => + { let substs = - relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; + relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?; return Ok(tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: au.def, + substs, + promoted: au.promoted, + }), ty: a.ty, })); } @@ -591,9 +586,7 @@ // Both the variant and each field have to be equal. if a_destructured.variant == b_destructured.variant { - for (a_field, b_field) in - a_destructured.fields.iter().zip(b_destructured.fields.iter()) - { + for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) { relation.consts(a_field, b_field)?; } @@ -607,7 +600,7 @@ }) } -impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { fn relate>( relation: &mut R, a: Self, @@ -629,13 +622,12 @@ return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } - let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| { + let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| { use crate::ty::ExistentialPredicate::*; match (ep_a.skip_binder(), ep_b.skip_binder()) { - (Trait(a), Trait(b)) => Ok(ty::Binder::bind(Trait( - relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), - ))), - (Projection(a), Projection(b)) => Ok(ty::Binder::bind(Projection( + (Trait(a), Trait(b)) => Ok(ep_a + .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), + (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), ))), (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), @@ -698,12 +690,12 @@ } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder { +impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { fn relate>( relation: &mut R, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> { + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { relation.binders(a, b) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/structural_impls.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/structural_impls.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/structural_impls.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/structural_impls.rs 2021-06-17 03:53:50.000000000 +0000 @@ -454,10 +454,16 @@ } } -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { - type Lifted = ty::Binder; +impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T> +where + >::Lifted: TypeFoldable<'tcx>, +{ + type Lifted = ty::Binder<'tcx, T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - self.map_bound(|v| tcx.lift(v)).transpose() + let bound_vars = tcx.lift(self.bound_vars()); + tcx.lift(self.skip_binder()) + .zip(bound_vars) + .map(|(value, vars)| ty::Binder::bind_with_vars(value, vars)) } } @@ -581,6 +587,7 @@ UnsafetyMismatch(x) => UnsafetyMismatch(x), AbiMismatch(x) => AbiMismatch(x), Mutability => Mutability, + ArgumentMutability(i) => ArgumentMutability(i), TupleSize(x) => TupleSize(x), FixedArraySize(x) => FixedArraySize(x), ArgCount => ArgCount, @@ -601,6 +608,7 @@ CyclicTy(t) => return tcx.lift(t).map(|t| CyclicTy(t)), CyclicConst(ct) => return tcx.lift(ct).map(|ct| CyclicConst(ct)), ProjectionMismatched(x) => ProjectionMismatched(x), + ArgumentSorts(x, i) => return tcx.lift(x).map(|x| ArgumentSorts(x, i)), Sorts(x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(x) => return tcx.lift(x).map(ConstMismatch), @@ -749,7 +757,7 @@ } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { +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)) } @@ -767,7 +775,7 @@ } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { fn super_fold_with>(self, folder: &mut F) -> Self { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } @@ -1031,8 +1039,12 @@ 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(did, substs, promoted) => { - ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { + def, + substs: substs.fold_with(folder), + promoted, + }) } ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) @@ -1045,7 +1057,7 @@ match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), - ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor), + ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/sty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/sty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/sty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/sty.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,6 +5,8 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; +use crate::ty::fold::BoundVarsCollector; +use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; use crate::ty::{ @@ -62,22 +64,10 @@ #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] #[derive(HashStable)] pub struct BoundRegion { + pub var: BoundVar, pub kind: BoundRegionKind, } -impl BoundRegion { - /// When canonicalizing, we replace unbound inference variables and free - /// regions with anonymous late bound regions. This method asserts that - /// we have an anonymous late bound region, which hence may refer to - /// a canonical variable. - pub fn assert_bound_var(&self) -> BoundVar { - match self.kind { - BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var), - _ => bug!("bound region is not anonymous"), - } - } -} - impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { @@ -90,7 +80,7 @@ /// Defines the kinds of types. /// /// N.B., if you change this, you'll probably want to change the corresponding -/// AST structure in `librustc_ast/ast.rs` as well. +/// AST structure in `rustc_ast/src/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)] #[derive(HashStable)] #[rustc_diagnostic_item = "TyKind"] @@ -160,8 +150,8 @@ /// ``` FnPtr(PolyFnSig<'tcx>), - /// A trait, defined with `trait`. - Dynamic(&'tcx List>>, ty::Region<'tcx>), + /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. + Dynamic(&'tcx List>>, ty::Region<'tcx>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -173,7 +163,7 @@ /// A type representing the types stored inside a generator. /// This should only appear in GeneratorInteriors. - GeneratorWitness(Binder<&'tcx List>>), + GeneratorWitness(Binder<'tcx, &'tcx List>>), /// The never type `!`. Never, @@ -232,7 +222,7 @@ // `TyKind` 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!(TyKind<'_>, 24); +static_assert_size!(TyKind<'_>, 32); /// A closure can be modeled as a struct that looks like: /// @@ -747,7 +737,7 @@ } } -impl<'tcx> Binder> { +impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { @@ -768,7 +758,7 @@ } } -impl<'tcx> List>> { +impl<'tcx> List>> { /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) @@ -794,7 +784,7 @@ /// is `{Send, Sync}`, while there is no principal. These trait objects /// have a "trivial" vtable consisting of just the size, alignment, /// and destructor. - pub fn principal(&self) -> Option>> { + pub fn principal(&self) -> Option>> { self[0] .map_bound(|this| match this { ExistentialPredicate::Trait(tr) => Some(tr), @@ -810,7 +800,7 @@ #[inline] pub fn projection_bounds<'a>( &'a self, - ) -> impl Iterator>> + 'a { + ) -> impl Iterator>> + 'a { self.iter().filter_map(|predicate| { predicate .map_bound(|pred| match pred { @@ -875,10 +865,10 @@ } } -pub type PolyTraitRef<'tcx> = Binder>; +pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; impl<'tcx> PolyTraitRef<'tcx> { - pub fn self_ty(&self) -> Binder> { + pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|tr| tr.self_ty()) } @@ -931,7 +921,7 @@ } } -pub type PolyExistentialTraitRef<'tcx> = Binder>; +pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { @@ -947,52 +937,56 @@ } } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable)] +pub enum BoundVariableKind { + Ty(BoundTyKind), + Region(BoundRegionKind), + Const, +} + /// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == -/// Binder`). Note that when we instantiate, +/// Binder<'tcx, TraitRef>`). Note that when we instantiate, /// erase, or otherwise "discharge" these bound vars, we change the -/// type from `Binder` to just `T` (see +/// type from `Binder<'tcx, T>` to just `T` (see /// e.g., `liberate_late_bound_regions`). /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct Binder(T); +pub struct Binder<'tcx, T>(T, &'tcx List); -impl Binder { +impl<'tcx, T> Binder<'tcx, T> +where + T: TypeFoldable<'tcx>, +{ /// Wraps `value` in a binder, asserting that `value` does not /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. - pub fn dummy<'tcx>(value: T) -> Binder - where - T: TypeFoldable<'tcx>, - { + pub fn dummy(value: T) -> Binder<'tcx, T> { debug_assert!(!value.has_escaping_bound_vars()); - Binder(value) + Binder(value, ty::List::empty()) } /// Wraps `value` in a binder, binding higher-ranked vars (if any). - pub fn bind(value: T) -> Binder { - Binder(value) + pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> { + let mut collector = BoundVarsCollector::new(); + value.visit_with(&mut collector); + Binder(value, collector.into_vars(tcx)) } - /// Wraps `value` in a binder without actually binding any currently - /// unbound variables. - /// - /// Note that this will shift all debrujin indices of escaping bound variables - /// by 1 to avoid accidential captures. - pub fn wrap_nonbinding(tcx: TyCtxt<'tcx>, value: T) -> Binder - where - T: TypeFoldable<'tcx>, - { - if value.has_escaping_bound_vars() { - Binder::bind(super::fold::shift_vars(tcx, value, 1)) - } else { - Binder::dummy(value) + pub fn bind_with_vars(value: T, vars: &'tcx List) -> Binder<'tcx, T> { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(vars); + value.visit_with(&mut validator); } + Binder(value, vars) } +} +impl<'tcx, T> Binder<'tcx, T> { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to @@ -1013,22 +1007,39 @@ self.0 } - pub fn as_ref(&self) -> Binder<&T> { - Binder(&self.0) + pub fn bound_vars(&self) -> &'tcx List { + self.1 } - pub fn map_bound_ref(&self, f: F) -> Binder + pub fn as_ref(&self) -> Binder<'tcx, &T> { + Binder(&self.0, self.1) + } + + pub fn map_bound_ref_unchecked(&self, f: F) -> Binder<'tcx, U> + where + F: FnOnce(&T) -> U, + { + let value = f(&self.0); + Binder(value, self.1) + } + + pub fn map_bound_ref>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { self.as_ref().map_bound(f) } - pub fn map_bound(self, f: F) -> Binder + pub fn map_bound>(self, f: F) -> Binder<'tcx, U> where F: FnOnce(T) -> U, { - Binder(f(self.0)) + let value = f(self.0); + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1040,8 +1051,15 @@ /// don't actually track bound vars. However, semantically, it is different /// because bound vars aren't allowed to change here, whereas they are /// in `bind`. This may be (debug) asserted in the future. - pub fn rebind(&self, value: U) -> Binder { - Binder(value) + pub fn rebind(&self, value: U) -> Binder<'tcx, U> + where + U: TypeFoldable<'tcx>, + { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.bound_vars()); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Unwraps and returns the value within, but only if it contains @@ -1054,45 +1072,32 @@ /// binders, but that would require adjusting the debruijn /// indices, and given the shallow binding structure we often use, /// would not be that useful.) - pub fn no_bound_vars<'tcx>(self) -> Option + pub fn no_bound_vars(self) -> Option where T: TypeFoldable<'tcx>, { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } - /// Given two things that have the same binder level, - /// and an operation that wraps on their contents, executes the operation - /// and then wraps its result. - /// - /// `f` should consider bound regions at depth 1 to be free, and - /// anything it produces with bound regions at depth 1 will be - /// bound in the resulting return value. - pub fn fuse(self, u: Binder, f: F) -> Binder - where - F: FnOnce(T, U) -> R, - { - Binder(f(self.0, u.0)) - } - /// Splits the contents into two things that share the same binder /// level as the original, returning two distinct binders. /// /// `f` should consider bound regions at depth 1 to be free, and /// anything it produces with bound regions at depth 1 will be /// bound in the resulting return values. - pub fn split(self, f: F) -> (Binder, Binder) + pub fn split(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>) where F: FnOnce(T) -> (U, V), { let (u, v) = f(self.0); - (Binder(u), Binder(v)) + (Binder(u, self.1), Binder(v, self.1)) } } -impl Binder> { - pub fn transpose(self) -> Option> { - self.0.map(Binder) +impl<'tcx, T> Binder<'tcx, Option> { + pub fn transpose(self) -> Option> { + let bound_vars = self.1; + self.0.map(|v| Binder(v, bound_vars)) } } @@ -1155,19 +1160,7 @@ pub return_ty: Ty<'tcx>, } -pub type PolyGenSig<'tcx> = Binder>; - -impl<'tcx> PolyGenSig<'tcx> { - pub fn resume_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.resume_ty) - } - pub fn yield_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.yield_ty) - } - pub fn return_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.return_ty) - } -} +pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. @@ -1205,22 +1198,22 @@ } } -pub type PolyFnSig<'tcx> = Binder>; +pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { #[inline] - pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { - self.map_bound_ref(|fn_sig| fn_sig.inputs()) + pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { + self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] - pub fn input(&self, index: usize) -> ty::Binder> { + pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } - pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List>> { + pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } #[inline] - pub fn output(&self) -> ty::Binder> { + pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output()) } pub fn c_variadic(&self) -> bool { @@ -1234,7 +1227,7 @@ } } -pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; +pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] @@ -1248,10 +1241,6 @@ ParamTy { index, name } } - pub fn for_self() -> ParamTy { - ParamTy::new(0, kw::SelfUpper) - } - pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { ParamTy::new(def.index, def.name) } @@ -1269,7 +1258,7 @@ pub name: Symbol, } -impl<'tcx> ParamConst { +impl ParamConst { pub fn new(index: u32, name: Symbol) -> ParamConst { ParamConst { index, name } } @@ -1277,10 +1266,6 @@ pub fn for_def(def: &ty::GenericParamDef) -> ParamConst { ParamConst::new(def.index, def.name) } - - pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - tcx.mk_const_param(self.index, self.name, ty) - } } pub type Region<'tcx> = &'tcx RegionKind; @@ -1486,7 +1471,7 @@ pub ty: Ty<'tcx>, } -pub type PolyExistentialProjection<'tcx> = Binder>; +pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; impl<'tcx> ExistentialProjection<'tcx> { /// Extracts the underlying existential trait reference from this projection. @@ -1580,35 +1565,6 @@ } } - /// Adjusts any De Bruijn indices so as to make `to_binder` the - /// innermost binder. That is, if we have something bound at `to_binder`, - /// it will now be bound at INNERMOST. This is an appropriate thing to do - /// when moving a region out from inside binders: - /// - /// ``` - /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _) - /// // Binder: D3 D2 D1 ^^ - /// ``` - /// - /// Here, the region `'a` would have the De Bruijn index D3, - /// because it is the bound 3 binders out. However, if we wanted - /// to refer to that region `'a` in the second argument (the `_`), - /// those two binders would not be in scope. In that case, we - /// might invoke `shift_out_to_binder(D3)`. This would adjust the - /// De Bruijn index of `'a` to D1 (the innermost binder). - /// - /// If we invoke `shift_out_to_binder` and the region is in fact - /// bound by one of the binders we are shifting out of, that is an - /// error (and should fail an assertion failure). - pub fn shifted_out_to_binder(&self, to_binder: ty::DebruijnIndex) -> RegionKind { - match *self { - ty::ReLateBound(debruijn, r) => { - ty::ReLateBound(debruijn.shifted_out_to_binder(to_binder), r) - } - r => r, - } - } - pub fn type_flags(&self) -> TypeFlags { let mut flags = TypeFlags::empty(); @@ -2160,7 +2116,7 @@ /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been - /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`) + /// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`) /// is complete, that type variable will be unified. pub fn to_opt_closure_kind(&self) -> Option { match self.kind() { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/subst.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/subst.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/subst.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/subst.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,6 @@ // Type substitutions. +use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; @@ -448,7 +449,10 @@ self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.binders_passed += 1; let t = t.super_fold_with(self); self.binders_passed -= 1; @@ -503,6 +507,11 @@ c.super_fold_with(self) } } + + #[inline] + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } impl<'a, 'tcx> SubstFolder<'a, 'tcx> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/trait_def.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/trait_def.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/trait_def.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/trait_def.rs 2021-06-17 03:53:50.000000000 +0000 @@ -35,6 +35,11 @@ /// and thus `impl`s of it are allowed to overlap. pub is_marker: bool, + /// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]` + /// attribute, indicating that editions before 2021 should not consider this trait + /// during method dispatch if the receiver is an array. + pub skip_array_during_method_dispatch: bool, + /// Used to determine whether the standard library is allowed to specialize /// on this trait. pub specialization_kind: TraitSpecializationKind, @@ -69,6 +74,12 @@ non_blanket_impls: FxHashMap>, } +impl TraitImpls { + pub fn blanket_impls(&self) -> &[DefId] { + self.blanket_impls.as_slice() + } +} + impl<'tcx> TraitDef { pub fn new( def_id: DefId, @@ -76,6 +87,7 @@ paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + skip_array_during_method_dispatch: bool, specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, ) -> TraitDef { @@ -85,6 +97,7 @@ paren_sugar, has_auto_impl, is_marker, + skip_array_during_method_dispatch, specialization_kind, def_path_hash, } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/util.rs 2021-06-17 03:53:50.000000000 +0000 @@ -18,10 +18,10 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; -use std::{cmp, fmt}; +use std::{fmt, iter}; #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { @@ -135,21 +135,6 @@ } } -/// Describes whether a type is representable. For types that are not -/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to -/// distinguish between types that are recursive with themselves and types that -/// contain a different recursive type. These cases can therefore be treated -/// differently when reporting errors. -/// -/// The ordering of the cases is significant. They are sorted so that cmp::max -/// will keep the "more erroneous" of two values. -#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] -pub enum Representability { - Representable, - ContainsRecursive, - SelfRecursive(Vec), -} - impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. @@ -414,9 +399,7 @@ _ => bug!(), }; - let result = item_substs - .iter() - .zip(impl_substs.iter()) + let result = iter::zip(item_substs, impl_substs) .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => { @@ -501,10 +484,9 @@ self, closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, - ) -> Option>> { + env_region: ty::RegionKind, + ) -> Option> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); - let br = ty::BoundRegion { kind: ty::BrEnv }; - let env_region = ty::ReLateBound(ty::INNERMOST, br); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { @@ -512,7 +494,7 @@ ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; - Some(ty::Binder::bind(env_ty)) + Some(env_ty) } /// Returns `true` if the node pointed to by `def_id` is a `static` item. @@ -701,7 +683,6 @@ /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - // FIXME: use `TyCtxtAt` instead of separate `Span`. pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) } @@ -741,6 +722,46 @@ } } + /// Checks whether values of this type `T` implement the `Unpin` trait. + pub fn is_unpin(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) + } + + /// Fast path helper for testing if a type is `Unpin`. + /// + /// Returning true means the type is known to be `Unpin`. Returning + /// `false` means nothing -- could be `Unpin`, might not be. + fn is_trivially_unpin(&self) -> bool { + match self.kind() { + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Never + | ty::Ref(..) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::Error(_) + | ty::FnPtr(_) => true, + ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_unpin), + ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), + ty::Adt(..) + | ty::Bound(..) + | ty::Closure(..) + | ty::Dynamic(..) + | ty::Foreign(_) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Infer(_) + | ty::Opaque(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Projection(_) => false, + } + } + /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely /// non-copy and *might* have a destructor attached; if it returns /// `false`, then `ty` definitely has no destructor (i.e., no drop glue). @@ -834,178 +855,6 @@ } } - /// Check whether a type is representable. This means it cannot contain unboxed - /// structural recursion. This check is needed for structs and enums. - pub fn is_representable(&'tcx self, tcx: TyCtxt<'tcx>, sp: Span) -> Representability { - // Iterate until something non-representable is found - fn fold_repr>(iter: It) -> Representability { - iter.fold(Representability::Representable, |r1, r2| match (r1, r2) { - (Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => { - Representability::SelfRecursive(v1.into_iter().chain(v2).collect()) - } - (r1, r2) => cmp::max(r1, r2), - }) - } - - fn are_inner_types_recursive<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - match ty.kind() { - Tuple(..) => { - // Find non representable - fold_repr(ty.tuple_fields().map(|ty| { - is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) - })) - } - // Fixed-length vectors. - // FIXME(#11924) Behavior undecided for zero-length vectors. - Array(ty, _) => { - is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) - } - Adt(def, substs) => { - // Find non representable fields with their spans - fold_repr(def.all_fields().map(|field| { - let ty = field.ty(tcx, substs); - let span = match field - .did - .as_local() - .map(|id| tcx.hir().local_def_id_to_hir_id(id)) - .and_then(|id| tcx.hir().find(id)) - { - Some(hir::Node::Field(field)) => field.ty.span, - _ => sp, - }; - match is_type_structurally_recursive( - tcx, - span, - seen, - representable_cache, - ty, - ) { - Representability::SelfRecursive(_) => { - Representability::SelfRecursive(vec![span]) - } - x => x, - } - })) - } - Closure(..) => { - // this check is run on type definitions, so we don't expect - // to see closure types - bug!("requires check invoked on inapplicable type: {:?}", ty) - } - _ => Representability::Representable, - } - } - - fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { - match *ty.kind() { - Adt(ty_def, _) => ty_def == def, - _ => false, - } - } - - // Does the type `ty` directly (without indirection through a pointer) - // contain any types on stack `seen`? - fn is_type_structurally_recursive<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); - if let Some(representability) = representable_cache.get(ty) { - debug!( - "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", - ty, sp, representability - ); - return representability.clone(); - } - - let representability = - is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty); - - representable_cache.insert(ty, representability.clone()); - representability - } - - fn is_type_structurally_recursive_inner<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - match ty.kind() { - Adt(def, _) => { - { - // Iterate through stack of previously seen types. - let mut iter = seen.iter(); - - // The first item in `seen` is the type we are actually curious about. - // We want to return SelfRecursive if this type contains itself. - // It is important that we DON'T take generic parameters into account - // for this check, so that Bar in this example counts as SelfRecursive: - // - // struct Foo; - // struct Bar { x: Bar } - - if let Some(&seen_type) = iter.next() { - if same_struct_or_enum(seen_type, *def) { - debug!("SelfRecursive: {:?} contains {:?}", seen_type, ty); - return Representability::SelfRecursive(vec![sp]); - } - } - - // We also need to know whether the first item contains other types - // that are structurally recursive. If we don't catch this case, we - // will recurse infinitely for some inputs. - // - // It is important that we DO take generic parameters into account - // here, so that code like this is considered SelfRecursive, not - // ContainsRecursive: - // - // struct Foo { Option> } - - for &seen_type in iter { - if ty::TyS::same_type(ty, seen_type) { - debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty); - return Representability::ContainsRecursive; - } - } - } - - // For structs and enums, track all previously seen types by pushing them - // onto the 'seen' stack. - seen.push(ty); - let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty); - seen.pop(); - out - } - _ => { - // No need to push in other cases. - are_inner_types_recursive(tcx, sp, seen, representable_cache, ty) - } - } - } - - debug!("is_type_representable: {:?}", self); - - // To avoid a stack overflow when checking an enum variant or struct that - // contains a different, structurally recursive type, maintain a stack - // of seen types and check recursion for each of them (issues #3008, #3779). - let mut seen: Vec> = Vec::new(); - let mut representable_cache = FxHashMap::default(); - let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, self); - debug!("is_type_representable: {:?} is {:?}", self, r); - r - } - /// Peel off all reference types in this type until there are none left. /// /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/walk.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/walk.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_middle/src/ty/walk.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_middle/src/ty/walk.rs 2021-06-17 03:53:50.000000000 +0000 @@ -195,8 +195,8 @@ | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Unevaluated(_, substs, _) => { - stack.extend(substs.iter().rev()); + ty::ConstKind::Unevaluated(ct) => { + stack.extend(ct.substs.iter().rev()); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs 2021-06-17 03:53:50.000000000 +0000 @@ -197,7 +197,11 @@ ); } } - FnSelfUseKind::Normal { self_arg, implicit_into_iter } => { + FnSelfUseKind::Normal { + self_arg, + implicit_into_iter, + is_option_or_result, + } => { if implicit_into_iter { err.span_label( fn_call_span, @@ -215,6 +219,14 @@ ), ); } + if is_option_or_result { + err.span_suggestion_verbose( + fn_call_span.shrink_to_lo(), + "consider calling `.as_ref()` to borrow the type's contents", + "as_ref().".to_string(), + Applicability::MachineApplicable, + ); + } // Avoid pointing to the same function in multiple different // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) @@ -264,7 +276,24 @@ if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { let sess = self.infcx.tcx.sess; - if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { + let ty = used_place.ty(self.body, self.infcx.tcx).ty; + // If we have a `&mut` ref, we need to reborrow. + if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { + // If we are in a loop this will be suggested later. + if !is_loop_move { + err.span_suggestion_verbose( + move_span.shrink_to_lo(), + &format!( + "consider creating a fresh reborrow of {} here", + self.describe_place(moved_place.as_ref()) + .map(|n| format!("`{}`", n)) + .unwrap_or_else(|| "the mutable reference".to_string()), + ), + format!("&mut *"), + Applicability::MachineApplicable, + ); + } + } else if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { err.span_suggestion( move_span, "consider borrowing to avoid moving into the for loop", @@ -1664,7 +1693,7 @@ if decl.can_be_made_mutable() { err.span_suggestion( decl.source_info.span, - "make this binding mutable", + "consider making this binding mutable", format!("mut {}", name), Applicability::MachineApplicable, ); @@ -1728,7 +1757,7 @@ impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { match statement { - Statement { kind: StatementKind::FakeRead(cause, box place), .. } + Statement { kind: StatementKind::FakeRead(box (cause, place)), .. } if *place == self.place => { self.cause = Some(*cause); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs 2021-06-17 03:53:50.000000000 +0000 @@ -515,7 +515,7 @@ let block = &self.body.basic_blocks()[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), + kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)), .. }) = block.statements.get(location.statement_index) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -7,8 +7,8 @@ use rustc_hir::lang_items::LangItemGroup; use rustc_hir::GeneratorKind; use rustc_middle::mir::{ - AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place, - PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, + Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt}; @@ -18,6 +18,7 @@ Span, }; use rustc_target::abi::VariantIdx; +use std::iter; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -501,7 +502,7 @@ // lifetimes without names with the value `'0`. match ty.kind() { ty::Ref( - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, @@ -522,7 +523,7 @@ let region = match ty.kind() { ty::Ref(region, _, _) => { match region { - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { printer.region_highlight_mode.highlighting_bound_region(*br, counter) } @@ -572,7 +573,13 @@ #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) enum FnSelfUseKind<'tcx> { /// A normal method call of the form `receiver.foo(a, b, c)` - Normal { self_arg: Ident, implicit_into_iter: bool }, + Normal { + self_arg: Ident, + implicit_into_iter: bool, + /// Whether the self type of the method call has an `.as_ref()` method. + /// Used for better diagnostics. + is_option_or_result: bool, + }, /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)` FnOnceCall, /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`) @@ -794,6 +801,24 @@ } } + // StatementKind::FakeRead only contains a def_id if they are introduced as a result + // of pattern matching within a closure. + if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind { + match cause { + FakeReadCause::ForMatchedPlace(Some(closure_def_id)) + | FakeReadCause::ForLet(Some(closure_def_id)) => { + debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place); + let places = &[Operand::Move(*place)]; + if let Some((args_span, generator_kind, var_span)) = + self.closure_span(closure_def_id, moved_place, places) + { + return ClosureUse { generator_kind, args_span, var_span }; + } + } + _ => {} + } + } + let normal_ret = if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) { PatUse(stmt.source_info.span) @@ -881,7 +906,17 @@ fn_call_span.desugaring_kind(), Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) ); - FnSelfUseKind::Normal { self_arg, implicit_into_iter } + let parent_self_ty = parent + .filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl) + .and_then(|did| match tcx.type_of(did).kind() { + ty::Adt(def, ..) => Some(def.did), + _ => None, + }); + let is_option_or_result = parent_self_ty.map_or(false, |def_id| { + tcx.is_diagnostic_item(sym::option_type, def_id) + || tcx.is_diagnostic_item(sym::result_type, def_id) + }); + FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } }); return FnSelfUse { @@ -970,13 +1005,10 @@ let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr { - for (captured_place, place) in self - .infcx - .tcx - .typeck(def_id.expect_local()) - .closure_min_captures_flattened(def_id) - .zip(places) - { + for (captured_place, place) in iter::zip( + self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id), + places, + ) { let upvar_hir_id = captured_place.get_root_variable(); //FIXME(project-rfc-2229#8): Use better span from captured_place let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,4 @@ -//! Contains utilities for generating suggestions for borrowck errors related to unsatisified +//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. use std::collections::BTreeMap; @@ -157,7 +157,7 @@ debug!("Collected {:?}: {:?}", fr, outlived_fr); // Add to set of constraints for final help note. - self.constraints_to_add.entry(fr).or_insert(Vec::new()).push(outlived_fr); + self.constraints_to_add.entry(fr).or_default().push(outlived_fr); } /// Emit an intermediate note on the given `Diagnostic` if the involved regions are diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,5 @@ use std::fmt::{self, Display}; +use std::iter; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; @@ -536,7 +537,8 @@ // just worry about trying to match up the rustc type // with the HIR types: (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { - search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(*elem_hir_tys)); + search_stack + .extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys)); } (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) @@ -611,7 +613,7 @@ args: &'hir hir::GenericArgs<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option<&'hir hir::Lifetime> { - for (kind, hir_arg) in substs.iter().zip(args.args) { + for (kind, hir_arg) in iter::zip(substs, args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { if r.to_region_vid() == needle_fr { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/invalidation.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/invalidation.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/invalidation.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/invalidation.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,6 +5,7 @@ use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::mir::{Statement, StatementKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use crate::dataflow::indexes::BorrowIndex; @@ -62,14 +63,14 @@ self.mutate_place(location, *lhs, Shallow(None), JustWrite); } - StatementKind::FakeRead(_, _) => { + StatementKind::FakeRead(box (_, _)) => { // Only relevant for initialized/liveness/safety checks. } StatementKind::SetDiscriminant { place, variant_index: _ } => { self.mutate_place(location, **place, Shallow(None), JustWrite); } StatementKind::LlvmInlineAsm(asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. @@ -203,8 +204,7 @@ } => { for op in operands { match *op { - InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + InlineAsmOperand::In { reg: _, ref value } => { self.consume_operand(location, value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -218,7 +218,8 @@ self.mutate_place(location, out_place, Shallow(None), JustWrite); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -25,6 +25,7 @@ use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; +use std::iter; use std::mem; use std::rc::Rc; @@ -573,7 +574,7 @@ self.mutate_place(location, (*lhs, span), Shallow(None), JustWrite, flow_state); } - StatementKind::FakeRead(_, box ref place) => { + StatementKind::FakeRead(box (_, ref place)) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. @@ -595,7 +596,7 @@ self.mutate_place(location, (**place, span), Shallow(None), JustWrite, flow_state); } StatementKind::LlvmInlineAsm(ref asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. @@ -733,8 +734,7 @@ } => { for op in operands { match *op { - InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + InlineAsmOperand::In { reg: _, ref value } => { self.consume_operand(loc, (value, span), flow_state); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -760,7 +760,8 @@ ); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/places_conflict.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/places_conflict.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/places_conflict.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/places_conflict.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,6 +5,7 @@ use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, TyCtxt}; use std::cmp::max; +use std::iter; /// When checking if a place conflicts with another place, this enum is used to influence decisions /// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`. @@ -139,7 +140,7 @@ // loop invariant: borrow_c is always either equal to access_c or disjoint from it. for (i, (borrow_c, &access_c)) in - borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate() + iter::zip(borrow_place.projection, access_place.projection).enumerate() { debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c); let borrow_proj_base = &borrow_place.projection[..i]; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,5 @@ //! This module provides linkage between RegionInferenceContext and -//! librustc_graphviz traits, specialized to attaching borrowck analysis +//! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. use std::borrow::Cow; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs 2021-06-17 03:53:50.000000000 +0000 @@ -70,6 +70,12 @@ // Equate expected input tys with those in the MIR. for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() { + if argument_index + 1 >= body.local_decls.len() { + self.tcx() + .sess + .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); + break; + } // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/type_check/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -97,7 +97,7 @@ /// Type checks the given `mir` in the context of the inference /// context `infcx`. Returns any region constraints that have yet to -/// be proven. This result is includes liveness constraints that +/// be proven. This result includes liveness constraints that /// ensure that regions appearing in the types of all local variables /// are live at all points where that local variable may later be /// used. @@ -316,14 +316,12 @@ let tcx = self.tcx(); let maybe_uneval = match constant.literal { ConstantKind::Ty(ct) => match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { - Some((def, substs, promoted)) - } + ty::ConstKind::Unevaluated(uv) => Some(uv), _ => None, }, _ => None, }; - if let Some((def, substs, promoted)) = maybe_uneval { + if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval { if let Some(promoted) = promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, promoted: &Body<'tcx>, @@ -1772,7 +1770,7 @@ if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { @@ -2030,7 +2028,7 @@ traits::ObligationCauseCode::RepeatVec(is_const_fn), ), self.param_env, - ty::Binder::bind(ty::TraitRef::new( + ty::Binder::dummy(ty::TraitRef::new( self.tcx().require_lang_item( LangItem::Copy, Some(self.last_span), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/universal_regions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/universal_regions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/universal_regions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/borrow_check/universal_regions.rs 2021-06-17 03:53:50.000000000 +0000 @@ -580,7 +580,7 @@ let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - identity_substs.regions().zip(fr_substs.regions().map(|r| r.to_region_vid())); + iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() } } @@ -589,31 +589,45 @@ &self, indices: &UniversalRegionIndices<'tcx>, defining_ty: DefiningTy<'tcx>, - ) -> ty::Binder<&'tcx ty::List>> { + ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; match defining_ty { DefiningTy::Closure(def_id, substs) => { assert_eq!(self.mir_def.did.to_def_id(), def_id); let closure_sig = substs.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); - let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| { - // The "inputs" of the closure in the - // signature appear as a tuple. The MIR side - // flattens this tuple. - let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); - assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let inputs = match tuplized_inputs[0].kind() { - ty::Tuple(inputs) => inputs, - _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), - }; + let bound_vars = tcx.mk_bound_variable_kinds( + inputs_and_output + .bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + // The "inputs" of the closure in the + // signature appear as a tuple. The MIR side + // flattens this tuple. + let (&output, tuplized_inputs) = + inputs_and_output.skip_binder().split_last().unwrap(); + assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); + let inputs = match tuplized_inputs[0].kind() { + ty::Tuple(inputs) => inputs, + _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), + }; + ty::Binder::bind_with_vars( tcx.mk_type_list( iter::once(closure_ty) .chain(inputs.iter().map(|k| k.expect_ty())) .chain(iter::once(output)), - ) - }) + ), + bound_vars, + ) } DefiningTy::Generator(def_id, substs, movability) => { @@ -657,7 +671,7 @@ &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where @@ -686,7 +700,7 @@ &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/eval_queries.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/eval_queries.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/eval_queries.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/eval_queries.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,6 +5,7 @@ Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, ScalarMaybeUninit, StackPopCleanup, }; +use crate::util::pretty::display_allocation; use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; @@ -360,6 +361,15 @@ "it is undefined behavior to use this value", |mut diag| { diag.note(note_on_undefined_behavior_error()); + diag.note(&format!( + "the raw bytes of the constant ({}", + display_allocation( + *ecx.tcx, + ecx.tcx + .global_alloc(mplace.ptr.assert_ptr().alloc_id) + .unwrap_memory() + ) + )); diag.emit(); }, )) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/fn_queries.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/fn_queries.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/fn_queries.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/fn_queries.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,3 @@ -use rustc_attr as attr; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::map::blocks::FnLikeNode; @@ -34,54 +33,6 @@ } } -/// Returns `true` if this function must conform to `min_const_fn` -pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // Bail out if the signature doesn't contain `const` - if !tcx.is_const_fn_raw(def_id) { - return false; - } - - if tcx.features().staged_api { - // In order for a libstd function to be considered min_const_fn - // it needs to be stable and have no `rustc_const_unstable` attribute. - match tcx.lookup_const_stability(def_id) { - // `rustc_const_unstable` functions don't need to conform. - Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false, - None => { - if let Some(stab) = tcx.lookup_stability(def_id) { - if stab.level.is_stable() { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - "stable const functions must have either `rustc_const_stable` or \ - `rustc_const_unstable` attribute", - ); - // While we errored above, because we don't know if we need to conform, we - // err on the "safe" side and require min_const_fn. - true - } else { - // Unstable functions need not conform to min_const_fn. - false - } - } else { - // Internal functions are forced to conform to min_const_fn. - // Annotate the internal function with a const stability attribute if - // you need to use unstable features. - // Note: this is an arbitrary choice that does not affect stability or const - // safety or anything, it just changes whether we need to annotate some - // internal functions with `rustc_const_stable` or with `rustc_const_unstable` - true - } - } - // Everything else needs to conform, because it would be callable from - // other `min_const_fn` functions. - _ => true, - } - } else { - // users enabling the `const_fn` feature gate can do what they want - !tcx.features().const_fn - } -} - pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { let parent_id = tcx.hir().get_parent_did(hir_id); if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/machine.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/machine.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/machine.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/machine.rs 2021-06-17 03:53:50.000000000 +0000 @@ -53,7 +53,7 @@ /// Extra machine state for CTFE, and the Machine instance pub struct CompileTimeInterpreter<'mir, 'tcx> { /// For now, the number of terminators that can be evaluated before we throw a resource - /// exhuastion error. + /// exhaustion error. /// /// Setting this to `0` disables the limit and allows the interpreter to run forever. pub steps_remaining: usize, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/const_eval/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/const_eval/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -110,7 +110,7 @@ let variant = ecx.read_discriminant(&place.into()).unwrap().1; - branches(def.variants[variant].fields.len(), Some(variant)) + branches(def.variants[variant].fields.len(), def.is_enum().then_some(variant)) } ty::Never diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/cursor.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/cursor.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/cursor.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/cursor.rs 2021-06-17 03:53:50.000000000 +0000 @@ -64,10 +64,6 @@ } } - pub fn body(&self) -> &'mir mir::Body<'tcx> { - self.body - } - /// Returns the underlying `Results`. pub fn results(&self) -> &Results<'tcx, A> { &self.results.borrow() diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/lattice.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/lattice.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/lattice.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/lattice.rs 2021-06-17 03:53:50.000000000 +0000 @@ -40,6 +40,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; +use std::iter; /// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements /// in the set. @@ -110,7 +111,7 @@ assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.join(b); } changed @@ -122,7 +123,7 @@ assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.meet(b); } changed diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/framework/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -510,7 +510,7 @@ } } - /// Returns `true` if the effect at `self` should be applied eariler than the effect at `other` + /// Returns `true` if the effect at `self` should be applied earlier than the effect at `other` /// in forward order. fn precedes_in_forward_order(self, other: Self) -> bool { let ord = self diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/impls/borrows.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/impls/borrows.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/impls/borrows.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/impls/borrows.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,6 +11,7 @@ use crate::dataflow::{self, fmt::DebugWithContext, GenKill}; use std::fmt; +use std::iter; rustc_index::newtype_index! { pub struct BorrowIndex { @@ -292,7 +293,7 @@ } mir::StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect && !kind.is_rw { self.kill_borrows_on_place(trans, *output); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/move_paths/builder.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/move_paths/builder.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/dataflow/move_paths/builder.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/dataflow/move_paths/builder.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,6 +4,7 @@ use rustc_middle::ty::{self, TyCtxt}; use smallvec::{smallvec, SmallVec}; +use std::iter; use std::mem; use super::abs_domain::Lift; @@ -292,11 +293,11 @@ } self.gather_rvalue(rval); } - StatementKind::FakeRead(_, place) => { - self.create_move_path(**place); + StatementKind::FakeRead(box (_, place)) => { + self.create_move_path(*place); } StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect { self.gather_init(output.as_ref(), InitKind::Deep); } @@ -424,7 +425,7 @@ for op in operands { match *op { InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + => { self.gather_operand(value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -440,7 +441,8 @@ self.gather_init(out_place.as_ref(), InitKind::Deep); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/eval_context.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/eval_context.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/eval_context.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/eval_context.rs 2021-06-17 03:53:50.000000000 +0000 @@ -232,6 +232,8 @@ /// this frame (can happen e.g. during frame initialization, and during unwinding on /// frames without cleanup code). /// We basically abuse `Result` as `Either`. + /// + /// Used by priroda. pub fn current_loc(&self) -> Result { self.loc } @@ -460,11 +462,6 @@ } #[inline] - pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx, self.param_env) - } - - #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { ty.is_freeze(self.tcx, self.param_env) } @@ -527,6 +524,7 @@ } } + #[inline(always)] pub fn layout_of_local( &self, frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs 2021-06-17 03:53:50.000000000 +0000 @@ -74,7 +74,7 @@ fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/intrinsics.rs 2021-06-17 03:53:50.000000000 +0000 @@ -171,8 +171,7 @@ }; let val = self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?; - let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; - let val = self.const_to_op(&const_, None)?; + let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest)?; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/operand.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/operand.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/interpret/operand.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/interpret/operand.rs 2021-06-17 03:53:50.000000000 +0000 @@ -77,14 +77,6 @@ pub fn to_scalar(self) -> InterpResult<'tcx, Scalar> { self.to_scalar_or_uninit().check_init() } - - #[inline] - pub fn to_scalar_pair(self) -> InterpResult<'tcx, (Scalar, Scalar)> { - match self { - Immediate::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"), - Immediate::ScalarPair(a, b) => Ok((a.check_init()?, b.check_init()?)), - } - } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together @@ -233,7 +225,7 @@ } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST. + /// Normalize `place.ptr` to a `Pointer` if this is a place and not a ZST. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. #[inline] pub fn force_op_ptr( @@ -560,7 +552,7 @@ match val.val { ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { let instance = self.resolve(def, substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) } @@ -578,7 +570,7 @@ ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { match val { mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout), - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, None), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, layout), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,12 +11,12 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(map_try_insert)] #![feature(min_specialization)] @@ -26,7 +26,7 @@ #![feature(stmt_expr_attributes)] #![feature(trait_alias)] #![feature(option_get_or_insert_default)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(once_cell)] #![feature(control_flow_enum)] #![recursion_limit = "256"] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/collector.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/collector.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/collector.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/collector.rs 2021-06-17 03:53:50.000000000 +0000 @@ -59,11 +59,15 @@ //! //! ### Discovering roots //! -//! The roots of the mono item graph correspond to the non-generic +//! The roots of the mono item graph correspond to the public non-generic //! syntactic items in the source code. We find them by walking the HIR of the -//! crate, and whenever we hit upon a function, method, or static item, we -//! create a mono item consisting of the items DefId and, since we only -//! consider non-generic items, an empty type-substitution set. +//! crate, and whenever we hit upon a public function, method, or static item, +//! we create a mono item consisting of the items DefId and, since we only +//! consider non-generic items, an empty type-substitution set. (In eager +//! collection mode, during incremental compilation, all non-generic functions +//! are considered as roots, as well as when the `-Clink-dead-code` option is +//! specified. Functions marked `#[no_mangle]` and functions called by inlinable +//! functions also always act as roots.) //! //! ### Finding neighbor nodes //! Given a mono item node, we can discover neighbors by inspecting its @@ -184,7 +188,6 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; @@ -193,8 +196,11 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; use rustc_session::config::EntryFnType; +use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; +use rustc_target::abi::Size; use smallvec::SmallVec; use std::iter; use std::ops::Range; @@ -638,6 +644,35 @@ self.super_rvalue(rvalue, location); } + /// This does not walk the constant, as it has been handled entirely here and trying + /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily + /// work, as some constants cannot be represented in the type system. + fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) { + let literal = self.monomorphize(constant.literal); + let val = match literal { + mir::ConstantKind::Val(val, _) => val, + mir::ConstantKind::Ty(ct) => match ct.val { + ty::ConstKind::Value(val) => val, + ty::ConstKind::Unevaluated(ct) => { + let param_env = ty::ParamEnv::reveal_all(); + match self.tcx.const_eval_resolve(param_env, ct, None) { + // The `monomorphize` call should have evaluated that constant already. + Ok(val) => val, + Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => return, + Err(ErrorHandled::TooGeneric) => span_bug!( + self.body.source_info(location).span, + "collection encountered polymorphic constant: {:?}", + literal + ), + } + } + _ => return, + }, + }; + collect_const_value(self.tcx, val, self.output); + self.visit_ty(literal.ty(), TyContext::Location(location)); + } + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); @@ -646,9 +681,15 @@ match substituted_constant.val { ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output), - ty::ConstKind::Unevaluated(def, substs, promoted) => { - match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) { - Ok(val) => collect_const_value(self.tcx, val, self.output), + ty::ConstKind::Unevaluated(unevaluated) => { + match self.tcx.const_eval_resolve(param_env, unevaluated, None) { + // The `monomorphize` call should have evaluated that constant already. + Ok(val) => span_bug!( + self.body.source_info(location).span, + "collection encountered the unevaluated constant {} which evaluated to {:?}", + substituted_constant, + val + ), Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {} Err(ErrorHandled::TooGeneric) => span_bug!( self.body.source_info(location).span, @@ -714,6 +755,46 @@ self.super_terminator(terminator, location); } + fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { + self.super_operand(operand, location); + let limit = self.tcx.sess.move_size_limit(); + if limit == 0 { + return; + } + let limit = Size::from_bytes(limit); + let ty = operand.ty(self.body, self.tcx); + let ty = self.monomorphize(ty); + let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)); + if let Ok(layout) = layout { + if layout.size > limit { + debug!(?layout); + let source_info = self.body.source_info(location); + debug!(?source_info); + let lint_root = source_info.scope.lint_root(&self.body.source_scopes); + debug!(?lint_root); + let lint_root = match lint_root { + Some(lint_root) => lint_root, + // This happens when the issue is in a function from a foreign crate that + // we monomorphized in the current crate. We can't get a `HirId` for things + // in other crates. + // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root + // but correct span? This would make the lint at least accept crate-level lint attributes. + None => return, + }; + self.tcx.struct_span_lint_hir( + LARGE_ASSIGNMENTS, + lint_root, + source_info.span, + |lint| { + let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes())); + err.span_label(source_info.span, "value moved from here"); + err.emit() + }, + ); + } + } + } + fn visit_local( &mut self, _place_local: &Local, @@ -985,7 +1066,7 @@ tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode, output: &'a mut Vec>>, - entry_fn: Option<(LocalDefId, EntryFnType)>, + entry_fn: Option<(DefId, EntryFnType)>, } impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { @@ -1073,7 +1154,7 @@ && match self.mode { MonoItemCollectionMode::Eager => true, MonoItemCollectionMode::Lazy => { - self.entry_fn.map(|(id, _)| id) == Some(def_id) + self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id) || self.tcx.is_reachable_non_generic(def_id) || self .tcx @@ -1175,7 +1256,8 @@ let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -8,14 +8,14 @@ pub mod partitioning; pub mod polymorphize; -pub fn custom_coerce_unsize_info<'tcx>( +fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - let trait_ref = ty::Binder::bind(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), }); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/polymorphize.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/polymorphize.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/polymorphize.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/monomorphize/polymorphize.rs 2021-06-17 03:53:50.000000000 +0000 @@ -299,7 +299,7 @@ self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, _, Some(p)) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => @@ -310,10 +310,10 @@ self.visit_body(&promoted[p]); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, unevaluated_substs, None) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) if self.tcx.def_kind(def.did) == DefKind::AnonConst => { - self.visit_child_body(def.did, unevaluated_substs); + self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } _ => c.super_visit_with(self), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/ops.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/ops.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/ops.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/ops.rs 2021-06-17 03:53:50.000000000 +0000 @@ -540,12 +540,17 @@ pub struct UnsizingCast; impl NonConstOp for UnsizingCast { fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_unsize) + } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - mcf_build_error( - ccx, + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_unsize, span, "unsizing casts to types besides slices are not allowed in const fn", ) @@ -642,12 +647,17 @@ } fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_trait_bound) + } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - mcf_build_error( - ccx, + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_trait_bound, span, "trait bounds other than `Sized` on const fn parameters are unstable", ) @@ -672,21 +682,3 @@ } } } - -fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status { - if ccx.const_kind() != hir::ConstContext::ConstFn { - Status::Allowed - } else { - Status::Unstable(sym::const_fn) - } -} - -fn mcf_build_error(ccx: &ConstCx<'_, 'tcx>, span: Span, msg: &str) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg); - err.note( - "see issue #57563 \ - for more information", - ); - err.help("add `#![feature(const_fn)]` to the crate attributes to enable"); - err -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs 2021-06-17 03:53:50.000000000 +0000 @@ -79,7 +79,9 @@ mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) { - return; + bug!( + "Drop elaboration left behind a Drop for a type that does not need dropping" + ); } if dropped_place.is_indirect() { @@ -87,6 +89,10 @@ return; } + // Drop elaboration is not precise enough to accept code like + // `src/test/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option>` is + // initialized with `None` and never changed, it still emits drop glue. + // Hence we additionally check the qualifs here to allow more code to pass. if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) { // Use the span where the dropped local was declared for the error. let span = self.body.local_decls[dropped_place.local].source_info.span; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/qualifs.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/qualifs.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/qualifs.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/qualifs.rs 2021-06-17 03:53:50.000000000 +0000 @@ -29,11 +29,11 @@ /// Normally, we would determine what qualifications apply to each type and error when an illegal /// operation is performed on such a type. However, this was found to be too imprecise, especially /// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we -/// needn't reject code unless it actually constructs and operates on the qualifed variant. +/// needn't reject code unless it actually constructs and operates on the qualified variant. /// /// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a /// type-based one). Qualifications propagate structurally across variables: If a local (or a -/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed. +/// projection of a local) is assigned a qualified value, that local itself becomes qualified. pub trait Qualif { /// The name of the file used to debug the dataflow analysis that computes this qualif. const ANALYSIS_NAME: &'static str; @@ -247,7 +247,7 @@ // Check the qualifs of the value of `const` items. if let Some(ct) = constant.literal.const_for_ty() { - if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val { + if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val { assert!(promoted.is_none()); // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def.did).is_none() { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/validation.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/validation.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/validation.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_consts/validation.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported}; +use rustc_errors::{Applicability, Diagnostic, ErrorReported}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; use rustc_index::bit_set::BitSet; @@ -234,13 +234,11 @@ if self.is_const_stable_const_fn() { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) { - struct_span_err!( - self.ccx.tcx.sess, - self.span, - E0723, - "trait methods cannot be stable const fn" - ) - .emit(); + self.ccx + .tcx + .sess + .struct_span_err(self.span, "trait methods cannot be stable const fn") + .emit(); } } @@ -428,7 +426,7 @@ ty::PredicateKind::Subtype(_) => { bug!("subtype predicate on function: {:#?}", predicate) } - ty::PredicateKind::Trait(pred, constness) => { + ty::PredicateKind::Trait(pred, _constness) => { if Some(pred.def_id()) == tcx.lang_items().sized_trait() { continue; } @@ -442,16 +440,7 @@ // arguments when determining importance. let kind = LocalKind::Arg; - if constness == hir::Constness::Const { - self.check_op_spanned(ops::ty::TraitBound(kind), span); - } else if !tcx.features().const_fn - || self.ccx.is_const_stable_const_fn() - { - // HACK: We shouldn't need the conditional above, but trait - // bounds on containing impl blocks are wrongly being marked as - // "not-const". - self.check_op_spanned(ops::ty::TraitBound(kind), span); - } + self.check_op_spanned(ops::ty::TraitBound(kind), span); } // other kinds of bounds are either tautologies // or cause errors in other passes @@ -850,9 +839,12 @@ let obligation = Obligation::new( ObligationCause::dummy(), param_env, - Binder::bind(TraitPredicate { - trait_ref: TraitRef::from_method(tcx, trait_id, substs), - }), + Binder::bind( + TraitPredicate { + trait_ref: TraitRef::from_method(tcx, trait_id, substs), + }, + tcx, + ), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_packed_ref.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_packed_ref.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_packed_ref.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_packed_ref.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,11 +1,18 @@ +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; +use rustc_span::symbol::sym; use crate::transform::MirPass; use crate::util; +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; +} + pub struct CheckPackedRef; impl<'tcx> MirPass<'tcx> for CheckPackedRef { @@ -24,6 +31,41 @@ source_info: SourceInfo, } +fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { + let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| { + // FIXME: when we make this a hard error, this should have its + // own error code. + let message = if tcx.generics_of(def_id).own_requires_monomorphization() { + "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ + type or const parameters (error E0133)" + .to_string() + } else { + "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ + does not derive Copy (error E0133)" + .to_string() + }; + lint.build(&message).emit() + }); +} + +fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + debug!("builtin_derive_def_id({:?})", def_id); + if let Some(impl_def_id) = tcx.impl_of_method(def_id) { + if tcx.has_attr(impl_def_id, sym::automatically_derived) { + debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); + Some(impl_def_id) + } else { + debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); + None + } + } else { + debug!("builtin_derive_def_id({:?}) - not a method", def_id); + None + } +} + impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. @@ -40,26 +82,33 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - let source_info = self.source_info; - let lint_root = self.body.source_scopes[source_info.scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root; - self.tcx.struct_span_lint_hir( - UNALIGNED_REFERENCES, - lint_root, - source_info.span, - |lint| { - lint.build("reference to packed field is unaligned") - .note( - "fields of packed structs are not properly aligned, and creating \ - a misaligned reference is undefined behavior (even if that \ - reference is never dereferenced)", - ) - .emit() - }, - ); + let def_id = self.body.source.instance.def_id(); + if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) { + // If a method is defined in the local crate, + // the impl containing that method should also be. + self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); + } else { + let source_info = self.source_info; + let lint_root = self.body.source_scopes[source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + self.tcx.struct_span_lint_hir( + UNALIGNED_REFERENCES, + lint_root, + source_info.span, + |lint| { + lint.build("reference to packed field is unaligned") + .note( + "fields of packed structs are not properly aligned, and creating \ + a misaligned reference is undefined behavior (even if that \ + reference is never dereferenced)", + ) + .emit() + }, + ); + } } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_unsafety.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_unsafety.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/check_unsafety.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/check_unsafety.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,20 +10,15 @@ use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; +use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use rustc_span::symbol::sym; use std::ops::Bound; -use crate::const_eval::is_min_const_fn; -use crate::util; - pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, body_did: LocalDefId, const_context: bool, - min_const_fn: bool, violations: Vec, source_info: SourceInfo, tcx: TyCtxt<'tcx>, @@ -36,21 +31,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn new( const_context: bool, - min_const_fn: bool, body: &'a Body<'tcx>, body_did: LocalDefId, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Self { - // sanity check - if min_const_fn { - assert!(const_context); - } Self { body, body_did, const_context, - min_const_fn, violations: vec![], source_info: SourceInfo::outermost(body.span), tcx, @@ -86,7 +75,7 @@ let sig = func_ty.fn_sig(self.tcx); if let hir::Unsafety::Unsafe = sig.unsafety() { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::CallToUnsafeFunction, ) } @@ -136,7 +125,7 @@ match self.tcx.layout_scalar_valid_range(def.did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::InitializingTypeWith, ), } @@ -182,18 +171,6 @@ self.check_mut_borrowing_layout_constrained_field(*place, context.is_mutating_use()); } - // Check for borrows to packed fields. - // `is_disaligned` already traverses the place to consider all projections after the last - // `Deref`, so this only needs to be called once at the top level. - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - self.require_unsafe( - UnsafetyViolationKind::BorrowPacked, - UnsafetyViolationDetails::BorrowOfPackedField, - ); - } - } - // Some checks below need the extra metainfo of the local declaration. let decl = &self.body.local_decls[place.local]; @@ -227,7 +204,7 @@ let base_ty = base.ty(self.body, self.tcx).ty; if base_ty.is_unsafe_ptr() { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::DerefOfRawPointer, ) } @@ -272,7 +249,7 @@ ); if !nodrop { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::AssignToDroppingUnionField, ); } else { @@ -280,7 +257,7 @@ } } else { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::AccessToUnionField, ) } @@ -291,6 +268,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, '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); + let source_info = self.source_info; let lint_root = self.body.source_scopes[self.source_info.scope] .local_data @@ -317,25 +297,14 @@ // `unsafe` blocks are required in safe code Safety::Safe => { for violation in violations { - let mut violation = *violation; match violation.kind { - UnsafetyViolationKind::GeneralAndConstFn - | UnsafetyViolationKind::General => {} - UnsafetyViolationKind::BorrowPacked => { - if self.min_const_fn { - // const fns don't need to be backwards compatible and can - // emit these violations as a hard error instead of a backwards - // compat lint - violation.kind = UnsafetyViolationKind::General; - } - } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => { + UnsafetyViolationKind::General => {} + UnsafetyViolationKind::UnsafeFn => { bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - if !self.violations.contains(&violation) { - self.violations.push(violation) + if !self.violations.contains(violation) { + self.violations.push(*violation) } } false @@ -345,11 +314,7 @@ for violation in violations { let mut violation = *violation; - if violation.kind == UnsafetyViolationKind::BorrowPacked { - violation.kind = UnsafetyViolationKind::UnsafeFnBorrowPacked; - } else { - violation.kind = UnsafetyViolationKind::UnsafeFn; - } + violation.kind = UnsafetyViolationKind::UnsafeFn; if !self.violations.contains(&violation) { self.violations.push(violation) } @@ -362,31 +327,6 @@ if !violations.is_empty() { self.used_unsafe.insert(hir_id); } - // only some unsafety is allowed in const fn - if self.min_const_fn { - for violation in violations { - match violation.kind { - // these unsafe things are stable in const fn - UnsafetyViolationKind::GeneralAndConstFn => {} - // these things are forbidden in const fns - UnsafetyViolationKind::General - | UnsafetyViolationKind::BorrowPacked => { - let mut violation = *violation; - // const fns don't need to be backwards compatible and can - // emit these violations as a hard error instead of a backwards - // compat lint - violation.kind = UnsafetyViolationKind::General; - if !self.violations.contains(&violation) { - self.violations.push(violation) - } - } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => bug!( - "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context" - ), - } - } - } true } }; @@ -424,7 +364,7 @@ } else { continue; }; - self.require_unsafe(UnsafetyViolationKind::GeneralAndConstFn, details); + self.require_unsafe(UnsafetyViolationKind::General, details); } } } @@ -442,7 +382,7 @@ // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::CallToFunctionWith, ) } @@ -464,7 +404,6 @@ ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) }, - unsafe_derive_on_repr_packed, ..*providers }; } @@ -525,15 +464,12 @@ let param_env = tcx.param_env(def.did); let id = tcx.hir().local_def_id_to_hir_id(def.did); - let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Closure => (false, false), - hir::BodyOwnerKind::Fn => { - (tcx.is_const_fn_raw(def.did.to_def_id()), is_min_const_fn(tcx, def.did.to_def_id())) - } - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), + let const_context = match tcx.hir().body_owner_kind(id) { + hir::BodyOwnerKind::Closure => false, + hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()), + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true, }; - let mut checker = - UnsafetyChecker::new(const_context, min_const_fn, body, def.did, tcx, param_env); + let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env); checker.visit_body(&body); check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks); @@ -544,25 +480,6 @@ }) } -fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - - tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| { - // FIXME: when we make this a hard error, this should have its - // own error code. - let message = if tcx.generics_of(def_id).own_requires_monomorphization() { - "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ - type or const parameters (error E0133)" - .to_string() - } else { - "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ - does not derive Copy (error E0133)" - .to_string() - }; - lint.build(&message).emit() - }); -} - /// Returns the `HirId` for an enclosing scope that is also `unsafe`. fn is_enclosed( tcx: TyCtxt<'_>, @@ -609,22 +526,6 @@ }); } -fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - debug!("builtin_derive_def_id({:?})", def_id); - if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, sym::automatically_derived) { - debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); - Some(impl_def_id) - } else { - debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); - None - } - } else { - debug!("builtin_derive_def_id({:?}) - not a method", def_id); - None - } -} - pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { debug!("check_unsafety({:?})", def_id); @@ -643,7 +544,7 @@ if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" }; match kind { - UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => { + UnsafetyViolationKind::General => { // once struct_span_err!( tcx.sess, @@ -657,27 +558,6 @@ .note(note) .emit(); } - UnsafetyViolationKind::BorrowPacked => { - if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id.to_def_id()) { - // If a method is defined in the local crate, - // the impl containing that method should also be. - tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); - } else { - tcx.struct_span_lint_hir( - SAFE_PACKED_BORROWS, - lint_root, - source_info.span, - |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe{} block (error E0133)", - description, unsafe_fn_msg, - )) - .note(note) - .emit() - }, - ) - } - } UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir( UNSAFE_OP_IN_UNSAFE_FN, lint_root, @@ -692,35 +572,6 @@ .emit(); }, ), - UnsafetyViolationKind::UnsafeFnBorrowPacked => { - // When `unsafe_op_in_unsafe_fn` is disallowed, the behavior of safe and unsafe functions - // should be the same in terms of warnings and errors. Therefore, with `#[warn(safe_packed_borrows)]`, - // a safe packed borrow should emit a warning *but not an error* in an unsafe function, - // just like in a safe function, even if `unsafe_op_in_unsafe_fn` is `deny`. - // - // Also, `#[warn(unsafe_op_in_unsafe_fn)]` can't cause any new errors. Therefore, with - // `#[deny(safe_packed_borrows)]` and `#[warn(unsafe_op_in_unsafe_fn)]`, a packed borrow - // should only issue a warning for the sake of backwards compatibility. - // - // The solution those 2 expectations is to always take the minimum of both lints. - // This prevent any new errors (unless both lints are explicitly set to `deny`). - let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0 - <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0 - { - SAFE_PACKED_BORROWS - } else { - UNSAFE_OP_IN_UNSAFE_FN - }; - tcx.struct_span_lint_hir(&lint, lint_root, source_info.span, |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe block (error E0133)", - description, - )) - .span_label(source_info.span, description) - .note(note) - .emit(); - }) - } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/const_prop.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/const_prop.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/const_prop.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/const_prop.rs 2021-06-17 03:53:50.000000000 +0000 @@ -13,9 +13,9 @@ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc_middle::mir::{ - AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantKind, Local, LocalDecl, - LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, - Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, + AssertKind, BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind, + Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, + StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -440,18 +440,7 @@ } fn lint_root(&self, source_info: SourceInfo) -> Option { - let mut data = &self.source_scopes[source_info.scope]; - // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it - // does not work as I thought it would. Needs more investigation and documentation. - while data.inlined.is_some() { - trace!(?data); - data = &self.source_scopes[data.parent_scope.unwrap()]; - } - trace!(?data); - match &data.local_data { - ClearCrossCrate::Set(data) => Some(data.lint_root), - ClearCrossCrate::Clear => None, - } + source_info.scope.lint_root(&self.source_scopes) } fn use_ecx(&mut self, f: F) -> Option @@ -491,7 +480,11 @@ let lint_only = match c.literal { ConstantKind::Ty(ct) => match ct.val { // Promoteds must lint and not error as the user didn't ask for them - ConstKind::Unevaluated(_, _, Some(_)) => true, + ConstKind::Unevaluated(ty::Unevaluated { + def: _, + substs: _, + promoted: Some(_), + }) => true, // Out of backwards compatibility we cannot report hard errors in unused // generic functions using associated constants of the generic parameters. _ => c.literal.needs_subst(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/debug.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/debug.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/debug.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/debug.rs 2021-06-17 03:53:50.000000000 +0000 @@ -121,6 +121,7 @@ use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use std::lazy::SyncOnceCell; pub const NESTED_INDENT: &str = " "; @@ -703,9 +704,7 @@ let edge_counters = from_terminator .successors() .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); - edge_labels - .iter() - .zip(edge_counters) + iter::zip(&edge_labels, edge_counters) .map(|(label, some_counter)| { if let Some(counter) = some_counter { format!("{}\n{}", label, debug_counters.format_counter(counter)) @@ -817,7 +816,7 @@ sections } -/// Returns a simple string representation of a `TerminatorKind` variant, indenpendent of any +/// 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 { match kind { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -23,6 +23,7 @@ use rustc_middle::hir; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ich::StableHashingContext; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, @@ -87,6 +88,11 @@ _ => {} } + let codegen_fn_attrs = tcx.codegen_fn_attrs(mir_source.def_id()); + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + return; + } + trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); @@ -111,7 +117,8 @@ let body_span = hir_body.value.span; let source_file = source_map.lookup_source_file(body_span.lo()); let fn_sig_span = match some_fn_sig.filter(|fn_sig| { - Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi())) + fn_sig.span.ctxt() == body_span.ctxt() + && Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.lo())) }) { Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()), None => body_span.shrink_to_lo(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/query.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/query.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/query.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/query.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,10 +6,9 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each -/// counter) and `FunctionCoverage::new()` (to extract the coverage map metadata from the MIR). +/// A `query` provider for retrieving coverage information injected into MIR. pub(crate) fn provide(providers: &mut Providers) { - providers.coverageinfo = |tcx, def_id| coverageinfo_from_mir(tcx, def_id); + providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id); providers.covered_file_name = |tcx, def_id| covered_file_name(tcx, def_id); providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); } @@ -121,7 +120,7 @@ } } -fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { +fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { let mir_body = mir_body(tcx, def_id); let mut coverage_visitor = CoverageVisitor { @@ -139,29 +138,22 @@ } fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { - let body = mir_body(tcx, def_id); - for bb_data in body.basic_blocks().iter() { - for statement in bb_data.statements.iter() { - if let StatementKind::Coverage(box ref coverage) = statement.kind { - if let Some(code_region) = coverage.code_region.as_ref() { - if is_inlined(body, statement) { - continue; + if tcx.is_mir_available(def_id) { + let body = mir_body(tcx, def_id); + for bb_data in body.basic_blocks().iter() { + for statement in bb_data.statements.iter() { + if let StatementKind::Coverage(box ref coverage) = statement.kind { + if let Some(code_region) = coverage.code_region.as_ref() { + if is_inlined(body, statement) { + continue; + } + return Some(code_region.file_name); } - return Some(code_region.file_name); } } } } - None -} - -/// This function ensures we obtain the correct MIR for the given item irrespective of -/// whether that means const mir or runtime mir. For `const fn` this opts for runtime -/// mir. -fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { - let id = ty::WithOptConstParam::unknown(def_id); - let def = ty::InstanceDef::Item(id); - tcx.instance_mir(def) + return None; } fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> { @@ -188,3 +180,12 @@ let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() } + +/// This function ensures we obtain the correct MIR for the given item irrespective of +/// whether that means const mir or runtime mir. For `const fn` this opts for runtime +/// mir. +fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { + let id = ty::WithOptConstParam::unknown(def_id); + let def = ty::InstanceDef::Item(id); + tcx.instance_mir(def) +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/spans.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/spans.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/spans.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/spans.rs 2021-06-17 03:53:50.000000000 +0000 @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::source_map::original_sp; -use rustc_span::{BytePos, Span, SyntaxContext}; +use rustc_span::{BytePos, Span}; use std::cmp::Ordering; @@ -240,7 +240,7 @@ /// to be). pub(super) fn generate_coverage_spans( mir_body: &'a mir::Body<'tcx>, - fn_sig_span: Span, + fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span` body_span: Span, basic_coverage_blocks: &'a CoverageGraph, ) -> Vec { @@ -683,10 +683,10 @@ // and `_1` is the `Place` for `somenum`. // // If and when the Issue is resolved, remove this special case match pattern: - StatementKind::FakeRead(cause, _) if cause == FakeReadCause::ForGuardBinding => None, + StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None, // Retain spans from all other statements - StatementKind::FakeRead(_, _) // Not including `ForGuardBinding` + StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` | StatementKind::CopyNonOverlapping(..) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } @@ -717,11 +717,21 @@ | TerminatorKind::FalseEdge { .. } | TerminatorKind::Goto { .. } => None, + // Call `func` operand can have a more specific span when part of a chain of calls + | TerminatorKind::Call { ref func, .. } => { + let mut span = terminator.source_info.span; + if let mir::Operand::Constant(box constant) = func { + if constant.span.lo() > span.lo() { + span = span.with_lo(constant.span.lo()); + } + } + Some(function_source_span(span, body_span)) + } + // Retain spans from all other terminators TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Return - | TerminatorKind::Call { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseUnwind { .. } @@ -733,6 +743,6 @@ #[inline] fn function_source_span(span: Span, body_span: Span) -> Span { - let span = original_sp(span, body_span).with_ctxt(SyntaxContext::root()); + let span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); if body_span.contains(span) { span } else { body_span } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/tests.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/tests.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/tests.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/coverage/tests.rs 2021-06-17 03:53:50.000000000 +0000 @@ -17,7 +17,7 @@ //! Also note, some basic features of `Span` also rely on the `Span`s own "session globals", which //! are unrelated to the `TyCtxt` global. Without initializing the `Span` session globals, some //! basic, coverage-specific features would be impossible to test, but thankfully initializing these -//! globals is comparitively simpler. The easiest way is to wrap the test in a closure argument +//! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument //! to: `rustc_span::with_default_session_globals(|| { test_here(); })`. use super::counters; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/deduplicate_blocks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/deduplicate_blocks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/deduplicate_blocks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/deduplicate_blocks.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ //! This pass finds basic blocks that are completely equal, //! and replaces all uses with just one of them. -use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher}; +use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter}; use crate::transform::MirPass; @@ -115,11 +115,7 @@ 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 - && self - .basic_block_data - .statements - .iter() - .zip(&other.basic_block_data.statements) + && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements) .all(|(x, y)| statement_eq(&x.kind, &y.kind)) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/dest_prop.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/dest_prop.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/dest_prop.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/dest_prop.rs 2021-06-17 03:53:50.000000000 +0000 @@ -720,9 +720,6 @@ } } } - InlineAsmOperand::Const { value } => { - assert!(value.place().is_none()); - } InlineAsmOperand::InOut { reg: _, late: _, @@ -731,6 +728,7 @@ } | InlineAsmOperand::In { reg: _, value: _ } | InlineAsmOperand::Out { reg: _, late: _, place: None } + | InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/generator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/generator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/generator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/generator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -751,9 +751,10 @@ span_bug!( body.span, "Broken MIR: generator contains type {} in MIR, \ - but typeck only knows about {}", - decl.ty, - witness, + but typeck only knows about {} and {:?}", + decl_ty, + allowed, + allowed_upvars ); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/inline.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/inline.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/inline.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/inline.rs 2021-06-17 03:53:50.000000000 +0000 @@ -630,7 +630,7 @@ caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| { match ct.literal.const_for_ty() { - Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)), + Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)), None => true, } }), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/match_branches.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/match_branches.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/match_branches.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/match_branches.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,7 @@ use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use std::iter; use super::simplify::simplify_cfg; @@ -83,7 +84,7 @@ if first_stmts.len() != scnd_stmts.len() { continue; } - for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) { + for (f, s) in iter::zip(first_stmts, scnd_stmts) { match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. (f_s, s_s) if f_s == s_s => {} @@ -113,7 +114,7 @@ // and bb_idx has a different terminator from both of them. let (from, first, second) = bbs.pick3_mut(bb_idx, first, second); - let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| { + let new_stmts = iter::zip(&first.statements, &second.statements).map(|(f, s)| { match (&f.kind, &s.kind) { (f_s, s_s) if f_s == s_s => (*f).clone(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -44,6 +44,7 @@ pub mod remove_noop_landing_pads; pub mod remove_storage_markers; pub mod remove_unneeded_drops; +pub mod remove_zsts; pub mod required_consts; pub mod rustc_peek; pub mod simplify; @@ -58,6 +59,7 @@ pub(crate) fn provide(providers: &mut Providers) { self::check_unsafety::provide(providers); + self::check_packed_ref::provide(providers); *providers = Providers { mir_keys, mir_const, @@ -313,11 +315,8 @@ &simplify::SimplifyCfg::new("promote-consts"), ]; - let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage { - &[&coverage::InstrumentCoverage] - } else { - &[] - }; + let opt_coverage: &[&dyn MirPass<'tcx>] = + if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] }; run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); @@ -494,6 +493,7 @@ // 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, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/promote_consts.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/promote_consts.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/promote_consts.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/promote_consts.rs 2021-06-17 03:53:50.000000000 +0000 @@ -108,9 +108,6 @@ /// the attribute currently provides the semantic requirement that arguments /// must be constant. Argument { bb: BasicBlock, index: usize }, - - /// `const` operand in asm!. - InlineAsm { bb: BasicBlock, index: usize }, } impl Candidate { @@ -118,16 +115,14 @@ fn forces_explicit_promotion(&self) -> bool { match self { Candidate::Ref(_) => false, - Candidate::Argument { .. } | Candidate::InlineAsm { .. } => true, + Candidate::Argument { .. } => true, } } fn source_info(&self, body: &Body<'_>) -> SourceInfo { match self { Candidate::Ref(location) => *body.source_info(*location), - Candidate::Argument { bb, .. } | Candidate::InlineAsm { bb, .. } => { - *body.source_info(body.terminator_loc(*bb)) - } + Candidate::Argument { bb, .. } => *body.source_info(body.terminator_loc(*bb)), } } } @@ -217,36 +212,25 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { self.super_terminator(terminator, location); - match terminator.kind { - TerminatorKind::Call { ref func, .. } => { - if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() { - let fn_sig = self.ccx.tcx.fn_sig(def_id); - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { - let name = self.ccx.tcx.item_name(def_id); - // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. - if name.as_str().starts_with("simd_shuffle") { - self.candidates - .push(Candidate::Argument { bb: location.block, index: 2 }); - - return; // Don't double count `simd_shuffle` candidates - } - } - - if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) { - for index in constant_args { - self.candidates.push(Candidate::Argument { bb: location.block, index }); - } + if let TerminatorKind::Call { ref func, .. } = terminator.kind { + if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() { + let fn_sig = self.ccx.tcx.fn_sig(def_id); + if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { + let name = self.ccx.tcx.item_name(def_id); + // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. + if name.as_str().starts_with("simd_shuffle") { + self.candidates.push(Candidate::Argument { bb: location.block, index: 2 }); + + return; // Don't double count `simd_shuffle` candidates } } - } - TerminatorKind::InlineAsm { ref operands, .. } => { - for (index, op) in operands.iter().enumerate() { - if let InlineAsmOperand::Const { .. } = op { - self.candidates.push(Candidate::InlineAsm { bb: location.block, index }) + + if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) { + for index in constant_args { + self.candidates.push(Candidate::Argument { bb: location.block, index }); } } } - _ => {} } } } @@ -335,18 +319,6 @@ _ => bug!(), } } - Candidate::InlineAsm { bb, index } => { - assert!(self.explicit); - - let terminator = self.body[bb].terminator(); - match &terminator.kind { - TerminatorKind::InlineAsm { operands, .. } => match &operands[index] { - InlineAsmOperand::Const { value } => self.validate_operand(value), - _ => bug!(), - }, - _ => bug!(), - } - } } } @@ -818,9 +790,7 @@ } match candidate { - Candidate::Argument { bb, index } | Candidate::InlineAsm { bb, index } - if !is_promotable => - { + Candidate::Argument { bb, index } if !is_promotable => { let span = ccx.body[bb].terminator().source_info.span; let msg = format!("argument {} is required to be a constant", index + 1); ccx.tcx.sess.span_err(span, &msg); @@ -1001,17 +971,17 @@ literal: tcx .mk_const(ty::Const { ty, - val: ty::ConstKind::Unevaluated( + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, - InternalSubsts::for_item(tcx, def.did, |param, _| { + substs: InternalSubsts::for_item(tcx, def.did, |param, _| { if let ty::GenericParamDefKind::Lifetime = param.kind { tcx.lifetimes.re_erased.into() } else { tcx.mk_param_from_def(param) } }), - Some(promoted_id), - ), + promoted: Some(promoted_id), + }), }) .into(), })) @@ -1089,24 +1059,6 @@ _ => bug!(), } } - Candidate::InlineAsm { bb, index } => { - let terminator = blocks[bb].terminator_mut(); - match terminator.kind { - TerminatorKind::InlineAsm { ref mut operands, .. } => { - match &mut operands[index] { - InlineAsmOperand::Const { ref mut value } => { - let ty = value.ty(local_decls, self.tcx); - let span = terminator.source_info.span; - - Rvalue::Use(mem::replace(value, promoted_operand(ty, span))) - } - _ => bug!(), - } - } - - _ => bug!(), - } - } } }; @@ -1161,7 +1113,7 @@ } } } - Candidate::Argument { .. } | Candidate::InlineAsm { .. } => {} + Candidate::Argument { .. } => {} } // Declare return place local so that `mir::Body::new` doesn't complain. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/remove_zsts.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/remove_zsts.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/remove_zsts.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/remove_zsts.rs 2021-06-17 03:53:50.000000000 +0000 @@ -0,0 +1,89 @@ +//! Removes assignments to ZST places. + +use crate::transform::MirPass; +use rustc_middle::mir::tcx::PlaceTy; +use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind}; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +pub struct RemoveZsts; + +impl<'tcx> MirPass<'tcx> for RemoveZsts { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if tcx.sess.mir_opt_level() < 3 { + return; + } + let param_env = tcx.param_env(body.source.def_id()); + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + for block in basic_blocks.iter_mut() { + for statement in block.statements.iter_mut() { + match statement.kind { + StatementKind::Assign(box (place, _)) => { + let place_ty = place.ty(local_decls, tcx).ty; + if !maybe_zst(place_ty) { + continue; + } + let layout = match tcx.layout_of(param_env.and(place_ty)) { + Ok(layout) => layout, + Err(_) => continue, + }; + if !layout.is_zst() { + continue; + } + if involves_a_union(place, local_decls, tcx) { + continue; + } + if tcx.consider_optimizing(|| { + format!( + "RemoveZsts - Place: {:?} SourceInfo: {:?}", + place, statement.source_info + ) + }) { + statement.make_nop(); + } + } + _ => {} + } + } + } + } +} + +/// A cheap, approximate check to avoid unnecessary `layout_of` calls. +fn maybe_zst(ty: Ty<'_>) -> bool { + match ty.kind() { + // maybe ZST (could be more precise) + ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true, + // definitely ZST + ty::FnDef(..) | ty::Never => true, + // unreachable or can't be ZST + _ => false, + } +} + +/// Miri lazily allocates memory for locals on assignment, +/// so we must preserve writes to unions and union fields, +/// or it will ICE on reads of those fields. +fn involves_a_union<'tcx>( + place: Place<'tcx>, + local_decls: &LocalDecls<'tcx>, + tcx: TyCtxt<'tcx>, +) -> bool { + let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty); + if is_union(place_ty.ty) { + return true; + } + for elem in place.projection { + place_ty = place_ty.projection_ty(tcx, elem); + if is_union(place_ty.ty) { + return true; + } + } + return false; +} + +fn is_union(ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Adt(def, _) if def.is_union() => true, + _ => false, + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/required_consts.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/required_consts.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/required_consts.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/required_consts.rs 2021-06-17 03:53:50.000000000 +0000 @@ -15,7 +15,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, '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 { + if let ConstKind::Unevaluated(_) = ct.val { self.required_consts.push(*constant); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/simplify.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/simplify.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/transform/simplify.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/transform/simplify.rs 2021-06-17 03:53:50.000000000 +0000 @@ -31,10 +31,10 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::ParamEnv; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; -use std::{borrow::Cow, convert::TryInto}; +use std::borrow::Cow; +use std::convert::TryInto; pub struct SimplifyCfg { label: String, @@ -326,7 +326,7 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. - let mut used_locals = UsedLocals::new(body, tcx); + let mut used_locals = UsedLocals::new(body); // Next, we're going to remove any `Local` with zero actual uses. When we remove those // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` @@ -336,8 +336,7 @@ remove_unused_definitions(&mut used_locals, body); // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. - let arg_count = body.arg_count.try_into().unwrap(); - let map = make_local_map(&mut body.local_decls, &used_locals, arg_count); + let map = make_local_map(&mut body.local_decls, &used_locals); // Only bother running the `LocalUpdater` if we actually found locals to remove. if map.iter().any(Option::is_none) { @@ -350,61 +349,54 @@ } /// Construct the mapping while swapping out unused stuff out from the `vec`. -fn make_local_map<'tcx, V>( +fn make_local_map( local_decls: &mut IndexVec, - used_locals: &UsedLocals<'tcx>, - arg_count: u32, + used_locals: &UsedLocals, ) -> IndexVec> { - let mut map: IndexVec> = IndexVec::from_elem(None, local_decls); + let mut map: IndexVec> = IndexVec::from_elem(None, &*local_decls); let mut used = Local::new(0); for alive_index in local_decls.indices() { - // When creating the local map treat the `RETURN_PLACE` and arguments as used. - if alive_index.as_u32() <= arg_count || used_locals.is_used(alive_index) { - map[alive_index] = Some(used); - if alive_index != used { - local_decls.swap(alive_index, used); - } - used.increment_by(1); + // `is_used` treats the `RETURN_PLACE` and arguments as used. + if !used_locals.is_used(alive_index) { + continue; + } + + map[alive_index] = Some(used); + if alive_index != used { + local_decls.swap(alive_index, used); } + used.increment_by(1); } local_decls.truncate(used.index()); map } /// Keeps track of used & unused locals. -struct UsedLocals<'tcx> { +struct UsedLocals { increment: bool, + arg_count: u32, use_count: IndexVec, - is_static: bool, - local_decls: IndexVec>, - param_env: ParamEnv<'tcx>, - tcx: TyCtxt<'tcx>, } -impl UsedLocals<'tcx> { +impl UsedLocals { /// Determines which locals are used & unused in the given body. - fn new(body: &Body<'tcx>, tcx: TyCtxt<'tcx>) -> Self { - let def_id = body.source.def_id(); - let is_static = tcx.is_static(def_id); - let param_env = tcx.param_env(def_id); - let local_decls = body.local_decls.clone(); + fn new(body: &Body<'_>) -> Self { let mut this = Self { increment: true, + arg_count: body.arg_count.try_into().unwrap(), use_count: IndexVec::from_elem(0, &body.local_decls), - is_static, - local_decls, - param_env, - tcx, }; this.visit_body(body); this } /// Checks if local is used. + /// + /// Return place and arguments are always considered used. fn is_used(&self, local: Local) -> bool { trace!("is_used({:?}): use_count: {:?}", local, self.use_count[local]); - self.use_count[local] != 0 + local.as_u32() <= self.arg_count || self.use_count[local] != 0 } /// Updates the use counts to reflect the removal of given statement. @@ -422,7 +414,9 @@ // A use, not a definition. self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); } else { - // A definition. Although, it still might use other locals for indexing. + // A definition. The base local itself is not visited, so this occurrence is not counted + // toward its use count. There might be other locals still, used in an indexing + // projection. self.super_projection( place.as_ref(), PlaceContext::MutatingUse(MutatingUseContext::Projection), @@ -432,7 +426,7 @@ } } -impl Visitor<'tcx> for UsedLocals<'tcx> { +impl Visitor<'_> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::LlvmInlineAsm(..) @@ -459,21 +453,7 @@ } } - fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _location: Location) { - debug!("local: {:?} is_static: {:?}, ctx: {:?}", local, self.is_static, ctx); - // Do not count _0 as a used in `return;` if it is a ZST. - let return_place = *local == RETURN_PLACE - && matches!(ctx, PlaceContext::NonMutatingUse(visit::NonMutatingUseContext::Move)); - if !self.is_static && return_place { - let ty = self.local_decls[*local].ty; - let param_env_and = self.param_env.and(ty); - if let Ok(layout) = self.tcx.layout_of(param_env_and) { - debug!("layout.is_zst: {:?}", layout.is_zst()); - if layout.is_zst() { - return; - } - } - } + fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) { if self.increment { self.use_count[*local] += 1; } else { @@ -484,10 +464,7 @@ } /// Removes unused definitions. Updates the used locals to reflect the changes made. -fn remove_unused_definitions<'a, 'tcx>( - used_locals: &'a mut UsedLocals<'tcx>, - body: &mut Body<'tcx>, -) { +fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) { // 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.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/alignment.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/alignment.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/alignment.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/alignment.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,5 +1,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; +use rustc_target::abi::Align; /// Returns `true` if this place is allowed to be less aligned /// than its containing struct (because it is within a packed @@ -14,17 +15,25 @@ L: HasLocalDecls<'tcx>, { debug!("is_disaligned({:?})", place); - if !is_within_packed(tcx, local_decls, place) { - debug!("is_disaligned({:?}) - not within packed", place); - return false; - } + let pack = match is_within_packed(tcx, local_decls, place) { + None => { + debug!("is_disaligned({:?}) - not within packed", place); + return false; + } + Some(pack) => pack, + }; let ty = place.ty(local_decls, tcx).ty; match tcx.layout_raw(param_env.and(ty)) { - Ok(layout) if layout.align.abi.bytes() == 1 => { - // if the alignment is 1, the type can't be further - // disaligned. - debug!("is_disaligned({:?}) - align = 1", place); + Ok(layout) if layout.align.abi <= pack => { + // If the packed alignment is greater or equal to the field alignment, the type won't be + // further disaligned. + debug!( + "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", + place, + layout.align.abi.bytes(), + pack.bytes() + ); false } _ => { @@ -34,7 +43,11 @@ } } -fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: Place<'tcx>) -> bool +fn is_within_packed<'tcx, L>( + tcx: TyCtxt<'tcx>, + local_decls: &L, + place: Place<'tcx>, +) -> Option where L: HasLocalDecls<'tcx>, { @@ -45,7 +58,7 @@ ProjectionElem::Field(..) => { let ty = place_base.ty(local_decls, tcx).ty; match ty.kind() { - ty::Adt(def, _) if def.repr.packed() => return true, + ty::Adt(def, _) => return def.repr.pack, _ => {} } } @@ -53,5 +66,5 @@ } } - false + None } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/find_self_call.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/find_self_call.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/find_self_call.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/find_self_call.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -/// Checks if the specified `local` is used as the `self` prameter of a method call +/// Checks if the specified `local` is used as the `self` parameter of a method call /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is /// returned. pub fn find_self_call<'tcx>( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/generic_graphviz.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/generic_graphviz.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/generic_graphviz.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/generic_graphviz.rs 2021-06-17 03:53:50.000000000 +0000 @@ -40,22 +40,6 @@ } } - pub fn new_subgraph( - graph: &'a G, - graphviz_name: &str, - node_content_fn: NodeContentFn, - edge_labels_fn: EdgeLabelsFn, - ) -> Self { - Self { - graph, - is_subgraph: true, - graphviz_name: graphviz_name.to_owned(), - graph_label: None, - node_content_fn, - edge_labels_fn, - } - } - pub fn set_graph_label(&mut self, graph_label: &str) { self.graph_label = Some(graph_label.to_owned()); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/patch.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/patch.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/patch.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/patch.rs 2021-06-17 03:53:50.000000000 +0000 @@ -13,7 +13,6 @@ new_locals: Vec>, resume_block: BasicBlock, next_local: usize, - make_nop: Vec, } impl<'tcx> MirPatch<'tcx> { @@ -25,7 +24,6 @@ new_locals: vec![], next_local: body.local_decls.len(), resume_block: START_BLOCK, - make_nop: vec![], }; // make sure the MIR we create has a resume block. It is @@ -117,15 +115,7 @@ self.add_statement(loc, StatementKind::Assign(box (place, rv))); } - pub fn make_nop(&mut self, loc: Location) { - self.make_nop.push(loc); - } - pub fn apply(self, body: &mut Body<'tcx>) { - debug!("MirPatch: make nops at: {:?}", self.make_nop); - for loc in self.make_nop { - body.make_statement_nop(loc); - } debug!( "MirPatch: {:?} new temps, starting from index {}: {:?}", self.new_locals.len(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/pretty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/pretty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir/src/util/pretty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir/src/util/pretty.rs 2021-06-17 03:53:50.000000000 +0000 @@ -452,7 +452,11 @@ match literal { ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), ConstantKind::Val(val, ty) => { - self.push(&format!("+ literal: {:?}, {}", val, ty)) + // To keep the diffs small, we render this almost like we render ty::Const + self.push(&format!( + "+ literal: Const {{ ty: {}, val: Value({:?}) }}", + ty, val + )) } } } @@ -465,7 +469,21 @@ if use_verbose(ty) { self.push("ty::Const"); self.push(&format!("+ ty: {:?}", ty)); - self.push(&format!("+ val: {:?}", val)); + let val = match val { + ty::ConstKind::Param(p) => format!("Param({})", p), + ty::ConstKind::Infer(infer) => format!("Infer({:?})", infer), + ty::ConstKind::Bound(idx, var) => format!("Bound({:?}, {:?})", idx, var), + ty::ConstKind::Placeholder(ph) => format!("PlaceHolder({:?})", ph), + ty::ConstKind::Unevaluated(uv) => format!( + "Unevaluated({}, {:?}, {:?})", + self.tcx.def_path_str(uv.def.did), + uv.substs, + uv.promoted + ), + ty::ConstKind::Value(val) => format!("Value({:?})", val), + ty::ConstKind::Error(_) => format!("Error"), + }; + self.push(&format!("+ val: {}", val)); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/cfg.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/cfg.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/cfg.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/cfg.rs 2021-06-17 03:53:50.000000000 +0000 @@ -80,7 +80,7 @@ cause: FakeReadCause, place: Place<'tcx>, ) { - let kind = StatementKind::FakeRead(cause, box place); + let kind = StatementKind::FakeRead(box (cause, place)); let stmt = Statement { source_info, kind }; self.push(block, stmt); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_place.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_place.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_place.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_place.rs 2021-06-17 03:53:50.000000000 +0000 @@ -17,6 +17,8 @@ use rustc_index::vec::Idx; +use std::iter; + /// The "outermost" place that holds this value. #[derive(Copy, Clone, Debug, PartialEq)] crate enum PlaceBase { @@ -78,7 +80,7 @@ /// The projections are truncated to represent a path that might be captured by a /// closure/generator. This implies the vector returned from this function doesn't contain /// ProjectionElems `Downcast`, `ConstantIndex`, `Index`, or `Subslice` because those will never be -/// part of a path that is captued by a closure. We stop applying projections once we see the first +/// part of a path that is captured by a closure. We stop applying projections once we see the first /// projection that isn't captured by a closure. fn convert_to_hir_projections_and_truncate_for_capture<'tcx>( mir_projections: &[PlaceElem<'tcx>], @@ -140,7 +142,7 @@ return false; } - proj_possible_ancestor.iter().zip(proj_capture).all(|(a, b)| a == b) + iter::zip(proj_possible_ancestor, proj_capture).all(|(a, b)| a == b) } /// Computes the index of a capture within the desugared closure provided the closure's @@ -576,7 +578,7 @@ /// Lower a captured upvar. Note we might not know the actual capture index, /// so we create a place starting from `PlaceBase::Upvar`, which will be resolved - /// once all projections that allow us to indentify a capture have been applied. + /// once all projections that allow us to identify a capture have been applied. fn lower_captured_upvar( &mut self, block: BasicBlock, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs 2021-06-17 03:53:50.000000000 +0000 @@ -179,7 +179,9 @@ // match x { _ => () } // fake read of `x` // }; // ``` - // FIXME(RFC2229): Remove feature gate once diagnostics are improved + // + // FIXME(RFC2229, rust#85435): Remove feature gate once diagnostics are + // improved and unsafe checking works properly in closure bodies again. if this.tcx.features().capture_disjoint_fields { for (thir_place, cause, hir_id) in fake_reads.into_iter() { let place_builder = diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/into.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/into.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/into.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/expr/into.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,6 +10,7 @@ use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; +use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which @@ -110,18 +111,17 @@ ExprKind::LogicalOp { op, lhs, rhs } => { // And: // - // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block] - // | | (false) - // +----------false-----------+------------------> [false_block] + // [block: If(lhs)] -true-> [else_block: dest = (rhs)] + // | (false) + // [shortcurcuit_block: dest = false] // // Or: // - // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block] - // | (true) | (false) - // [true_block] [false_block] + // [block: If(lhs)] -false-> [else_block: dest = (rhs)] + // | (true) + // [shortcurcuit_block: dest = true] - let (true_block, false_block, mut else_block, join_block) = ( - this.cfg.start_new_block(), + let (shortcircuit_block, mut else_block, join_block) = ( this.cfg.start_new_block(), this.cfg.start_new_block(), this.cfg.start_new_block(), @@ -129,41 +129,31 @@ let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { - LogicalOp::And => (else_block, false_block), - LogicalOp::Or => (true_block, else_block), + LogicalOp::And => (else_block, shortcircuit_block), + LogicalOp::Or => (shortcircuit_block, else_block), }; let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); - let term = TerminatorKind::if_(this.tcx, rhs, true_block, false_block); - this.cfg.terminate(else_block, source_info, term); - this.cfg.push_assign_constant( - true_block, + shortcircuit_block, source_info, destination, Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, true).into(), + literal: match op { + LogicalOp::And => ty::Const::from_bool(this.tcx, false).into(), + LogicalOp::Or => ty::Const::from_bool(this.tcx, true).into(), + }, }, ); + this.cfg.goto(shortcircuit_block, source_info, join_block); - this.cfg.push_assign_constant( - false_block, - source_info, - destination, - Constant { - span: expr_span, - user_ty: None, - literal: ty::Const::from_bool(this.tcx, false).into(), - }, - ); + let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs)); + this.cfg.goto(else_block, source_info, join_block); - // Link up both branches: - this.cfg.goto(true_block, source_info, join_block); - this.cfg.goto(false_block, source_info, join_block); join_block.unit() } ExprKind::Loop { body } => { @@ -286,9 +276,7 @@ // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that // reads it from the base. - field_names - .into_iter() - .zip(field_types.into_iter()) + iter::zip(field_names, *field_types) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { @@ -367,9 +355,11 @@ }), } } - thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const { - value: unpack!(block = this.as_local_operand(block, expr)), - }, + thir::InlineAsmOperand::Const { value, span } => { + mir::InlineAsmOperand::Const { + value: box Constant { span, user_ty: None, literal: value.into() }, + } + } thir::InlineAsmOperand::SymFn { expr } => { mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/matches/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/matches/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/matches/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/matches/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -139,7 +139,7 @@ // uninhabited value. If we get never patterns, those will check that // the place is initialized, and so this read would only be used to // check safety. - let cause_matched_place = FakeReadCause::ForMatchedPlace; + let cause_matched_place = FakeReadCause::ForMatchedPlace(None); let source_info = self.source_info(scrutinee_span); if let Ok(scrutinee_builder) = @@ -400,7 +400,7 @@ // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); - self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet, place); + self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place); self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() @@ -435,7 +435,7 @@ // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); - let cause_let = FakeReadCause::ForLet; + let cause_let = FakeReadCause::ForLet(None); self.cfg.push_fake_read(block, pattern_source_info, cause_let, place); let ty_source_info = self.source_info(user_ty_span); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -252,8 +252,13 @@ _ => bug!("closure expr does not have closure type: {:?}", closure_ty), }; - let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); - tcx.erase_late_bound_regions(closure_env_ty) + let bound_vars = + tcx.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrEnv))); + let br = + ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap(); + tcx.erase_late_bound_regions(ty::Binder::bind_with_vars(closure_env_ty, bound_vars)) } #[derive(Debug, PartialEq, Eq)] @@ -604,6 +609,7 @@ | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/scope.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/scope.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/build/scope.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/build/scope.rs 2021-06-17 03:53:50.000000000 +0000 @@ -618,6 +618,13 @@ } } else { assert!(value.is_none(), "`return` and `break` should have a destination"); + if self.tcx.sess.instrument_coverage() { + // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which + // a Coverage code region can be generated, `continue` needs no `Assign`; but + // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for + // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR. + self.add_dummy_assignment(&span, block, source_info); + } } let region_scope = self.scopes.breakable_scopes[break_index].region_scope; @@ -643,6 +650,14 @@ self.cfg.start_new_block().unit() } + // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue` + // statement. + fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info: SourceInfo) { + let local_decl = LocalDecl::new(self.tcx.mk_unit(), *span).internal(); + let temp_place = Place::from(self.local_decls.push(local_decl)); + self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx); + } + crate fn exit_top_scope( &mut self, mut block: BasicBlock, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,13 +4,13 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] +#![feature(iter_zip)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/cx/expr.rs 2021-06-17 03:53:50.000000000 +0000 @@ -503,8 +503,12 @@ in_expr: self.mirror_expr(in_expr), out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), }, - hir::InlineAsmOperand::Const { ref expr } => { - InlineAsmOperand::Const { expr: self.mirror_expr(expr) } + hir::InlineAsmOperand::Const { ref anon_const } => { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let span = self.tcx.hir().span(anon_const.hir_id); + + InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::Sym { ref expr } => { let qpath = match expr.kind { @@ -707,11 +711,11 @@ // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); let lhs = mk_const(self.tcx().mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(did), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(did), substs, - None, - ), + promoted: None, + }), ty: var_ty, })); let bin = @@ -905,11 +909,11 @@ debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(def_id), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), substs, - None, - ), + promoted: None, + }), ty: self.typeck_results().node_type(expr.hir_id), }), user_ty, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -374,7 +374,8 @@ out_expr: Option<&'thir Expr<'thir, 'tcx>>, }, Const { - expr: &'thir Expr<'thir, 'tcx>, + value: &'tcx Const<'tcx>, + span: Span, }, SymFn { expr: &'thir Expr<'thir, 'tcx>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs 2021-06-17 03:53:50.000000000 +0000 @@ -246,6 +246,18 @@ }) } + fn field_pats( + &self, + vals: impl Iterator>, + ) -> Result>, FallbackToConstRef> { + vals.enumerate() + .map(|(idx, val)| { + let field = Field::new(idx); + Ok(FieldPat { field, pattern: self.recur(val, false)? }) + }) + .collect() + } + // Recursive helper for `to_pat`; invoke that (instead of calling this directly). fn recur( &self, @@ -257,16 +269,6 @@ let tcx = self.tcx(); let param_env = self.param_env; - let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| -> Result<_, _> { - vals.iter() - .enumerate() - .map(|(idx, val)| { - let field = Field::new(idx); - Ok(FieldPat { field, pattern: self.recur(val, false)? }) - }) - .collect() - }; - let kind = match cv.ty.kind() { ty::Float(_) => { tcx.struct_span_lint_hir( @@ -361,12 +363,12 @@ variant_index: destructured .variant .expect("destructed const of adt without variant id"), - subpatterns: field_pats(destructured.fields)?, + subpatterns: self.field_pats(destructured.fields.iter().copied())?, } } ty::Tuple(_) | ty::Adt(_, _) => { let destructured = tcx.destructure_const(param_env.and(cv)); - PatKind::Leaf { subpatterns: field_pats(destructured.fields)? } + PatKind::Leaf { subpatterns: self.field_pats(destructured.fields.iter().copied())? } } ty::Array(..) => PatKind::Array { prefix: tcx diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/lexer/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/lexer/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/lexer/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/lexer/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -128,7 +128,7 @@ } /// Turns simple `rustc_lexer::TokenKind` enum into a rich - /// `librustc_ast::TokenKind`. This turns strings into interned + /// `rustc_ast::TokenKind`. This turns strings into interned /// symbols and runs additional validation. fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Option { Some(match token { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,17 +1,21 @@ //! The main parser interface. +#![feature(array_windows)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] #![feature(iter_order_by)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_syntax)] #![feature(box_patterns)] #![recursion_limit = "256"] use rustc_ast as ast; -use rustc_ast::token::{self, Nonterminal}; -use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens, LazyTokenStream, TokenStream}; +use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; +use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_ast::AstLike; +use rustc_ast::Attribute; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diagnostic, FatalError, Level, PResult}; @@ -21,8 +25,6 @@ use std::path::Path; use std::str; -use tracing::debug; - pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments"); #[macro_use] @@ -255,19 +257,23 @@ // before we fall back to the stringification. let convert_tokens = - |tokens: Option<&LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream()); + |tokens: Option<&LazyTokenStream>| Some(tokens?.create_token_stream().to_tokenstream()); let tokens = match *nt { - Nonterminal::NtItem(ref item) => prepend_attrs(sess, &item.attrs, nt, item.tokens.as_ref()), + Nonterminal::NtItem(ref item) => prepend_attrs(&item.attrs, item.tokens.as_ref()), Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()), Nonterminal::NtStmt(ref stmt) => { - let do_prepend = |tokens| prepend_attrs(sess, stmt.attrs(), nt, tokens); if let ast::StmtKind::Empty = stmt.kind { - let tokens: TokenStream = - tokenstream::TokenTree::token(token::Semi, stmt.span).into(); - do_prepend(Some(&LazyTokenStream::new(tokens))) + let tokens = AttrAnnotatedTokenStream::new(vec![( + tokenstream::AttrAnnotatedTokenTree::Token(Token::new( + TokenKind::Semi, + stmt.span, + )), + Spacing::Alone, + )]); + prepend_attrs(&stmt.attrs(), Some(&LazyTokenStream::new(tokens))) } else { - do_prepend(stmt.tokens()) + prepend_attrs(&stmt.attrs(), stmt.tokens()) } } Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()), @@ -283,10 +289,7 @@ Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()), Nonterminal::NtTT(ref tt) => Some(tt.clone().into()), Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => { - if expr.tokens.is_none() { - debug!("missing tokens for expr {:?}", expr); - } - prepend_attrs(sess, &expr.attrs, nt, expr.tokens.as_ref()) + prepend_attrs(&expr.attrs, expr.tokens.as_ref()) } }; @@ -295,34 +298,30 @@ } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) { return fake_token_stream(sess, nt); } else { - panic!("Missing tokens for nt at {:?}: {:?}", nt.span(), pprust::nonterminal_to_string(nt)); + panic!( + "Missing tokens for nt {:?} at {:?}: {:?}", + nt, + nt.span(), + pprust::nonterminal_to_string(nt) + ); } } +fn prepend_attrs(attrs: &[Attribute], tokens: Option<&LazyTokenStream>) -> Option { + let tokens = tokens?; + if attrs.is_empty() { + return Some(tokens.create_token_stream().to_tokenstream()); + } + let attr_data = AttributesData { attrs: attrs.to_vec().into(), tokens: tokens.clone() }; + let wrapped = AttrAnnotatedTokenStream::new(vec![( + AttrAnnotatedTokenTree::Attributes(attr_data), + Spacing::Alone, + )]); + Some(wrapped.to_tokenstream()) +} + pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream { let source = pprust::nonterminal_to_string(nt); let filename = FileName::macro_expansion_source_code(&source); parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } - -fn prepend_attrs( - sess: &ParseSess, - attrs: &[ast::Attribute], - nt: &Nonterminal, - tokens: Option<&tokenstream::LazyTokenStream>, -) -> Option { - if attrs.is_empty() { - return Some(tokens?.create_token_stream()); - } - let mut builder = tokenstream::TokenStreamBuilder::new(); - for attr in attrs { - // FIXME: Correctly handle tokens for inner attributes. - // For now, we fall back to reparsing the original AST node - if attr.style == ast::AttrStyle::Inner { - return Some(fake_token_stream(sess, nt)); - } - builder.push(attr.tokens()); - } - builder.push(tokens?.create_token_stream()); - Some(builder.build()) -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/attr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/attr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/attr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/attr.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,10 +1,11 @@ -use super::{AttrWrapper, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Nonterminal}; use rustc_ast_pretty::pprust; use rustc_errors::{error_code, PResult}; use rustc_span::{sym, Span}; +use std::convert::TryInto; use tracing::debug; @@ -29,6 +30,7 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; + let start_pos = self.token_cursor.num_next_calls; loop { debug!("parse_outer_attributes: self.token={:?}", self.token); let attr = if self.check(&token::Pound) { @@ -74,7 +76,7 @@ break; } } - Ok(AttrWrapper::new(attrs)) + Ok(AttrWrapper::new(attrs.into(), start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -177,6 +179,7 @@ crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { + let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); // Only try to parse if it is an inner attribute (has `!`). let attr = if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) { Some(self.parse_attribute(InnerAttrPolicy::Permitted)?) @@ -191,6 +194,18 @@ None }; if let Some(attr) = attr { + let end_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); + // If we are currently capturing tokens, mark the location of this inner attribute. + // If capturing ends up creating a `LazyTokenStream`, we will include + // this replace range with it, removing the inner attribute from the final + // `AttrAnnotatedTokenStream`. Inner attributes are stored in the parsed AST note. + // During macro expansion, they are selectively inserted back into the + // token stream (the first inner attribute is remoevd each time we invoke the + // corresponding macro). + let range = start_pos..end_pos; + if let Capturing::Yes = self.capture_state.capturing { + self.capture_state.inner_attr_ranges.insert(attr.id, (range, vec![])); + } attrs.push(attr); } else { break; @@ -311,6 +326,9 @@ // One of the attributes may either itself be a macro, // or expand to macro attributes (`cfg_attr`). attrs.iter().any(|attr| { + if attr.is_doc_comment() { + return false; + } attr.ident().map_or(true, |ident| { ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name) }) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/attr_wrapper.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/attr_wrapper.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/attr_wrapper.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/attr_wrapper.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,12 +1,14 @@ -use super::attr; -use super::{ForceCollect, Parser, TokenCursor, TrailingToken}; -use rustc_ast::token::{self, Token, TokenKind}; -use rustc_ast::tokenstream::{CreateTokenStream, TokenStream, TokenTree, TreeAndSpacing}; -use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing}; -use rustc_ast::AstLike; +use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken}; +use rustc_ast::token::{self, DelimToken, Token, TokenKind}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttributesData, CreateTokenStream}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenTree, DelimSpan, LazyTokenStream, Spacing}; use rustc_ast::{self as ast}; +use rustc_ast::{AstLike, AttrVec, Attribute}; use rustc_errors::PResult; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; + +use std::convert::TryInto; +use std::ops::Range; /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens @@ -23,23 +25,158 @@ /// cannot directly access the `attrs` field #[derive(Debug, Clone)] pub struct AttrWrapper { - attrs: Vec, + attrs: AttrVec, + // The start of the outer attributes in the token cursor. + // This allows us to create a `ReplaceRange` for the entire attribute + // target, including outer attributes. + start_pos: usize, } +// This struct is passed around very frequently, +// so make sure it doesn't accidentally get larger +#[cfg(target_arch = "x86_64")] +rustc_data_structures::static_assert_size!(AttrWrapper, 16); + impl AttrWrapper { - pub fn empty() -> AttrWrapper { - AttrWrapper { attrs: vec![] } + pub(super) fn new(attrs: AttrVec, start_pos: usize) -> AttrWrapper { + AttrWrapper { attrs, start_pos } } - pub fn new(attrs: Vec) -> AttrWrapper { - AttrWrapper { attrs } + pub fn empty() -> AttrWrapper { + AttrWrapper { attrs: AttrVec::new(), start_pos: usize::MAX } } // FIXME: Delay span bug here? - pub(crate) fn take_for_recovery(self) -> Vec { + pub(crate) fn take_for_recovery(self) -> AttrVec { self.attrs } + + // FIXME: require passing an NT to prevent misuse of this method + pub(crate) fn prepend_to_nt_inner(self, attrs: &mut Vec) { + let mut self_attrs: Vec<_> = self.attrs.into(); + std::mem::swap(attrs, &mut self_attrs); + attrs.extend(self_attrs); + } + pub fn is_empty(&self) -> bool { self.attrs.is_empty() } + + pub fn maybe_needs_tokens(&self) -> bool { + crate::parser::attr::maybe_needs_tokens(&self.attrs) + } +} + +/// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute +fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool { + // NOTE: Builtin attributes like `cfg` and `cfg_attr` cannot be renamed via imports. + // Therefore, the absence of a literal `cfg` or `cfg_attr` guarantees that + // we don't need to do any eager expansion. + attrs.iter().any(|attr| { + attr.ident().map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr) + }) +} + +// Produces a `TokenStream` on-demand. Using `cursor_snapshot` +// and `num_calls`, we can reconstruct the `TokenStream` seen +// by the callback. This allows us to avoid producing a `TokenStream` +// if it is never needed - for example, a captured `macro_rules!` +// argument that is never passed to a proc macro. +// In practice token stream creation happens rarely compared to +// calls to `collect_tokens` (see some statistics in #78736), +// so we are doing as little up-front work as possible. +// +// This also makes `Parser` very cheap to clone, since +// there is no intermediate collection buffer to clone. +#[derive(Clone)] +struct LazyTokenStreamImpl { + start_token: (Token, Spacing), + cursor_snapshot: TokenCursor, + num_calls: usize, + break_last_token: bool, + replace_ranges: Box<[ReplaceRange]>, +} + +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(LazyTokenStreamImpl, 144); + +impl CreateTokenStream for LazyTokenStreamImpl { + fn create_token_stream(&self) -> AttrAnnotatedTokenStream { + // The token produced by the final call to `next` or `next_desugared` + // was not actually consumed by the callback. The combination + // of chaining the initial token and using `take` produces the desired + // result - we produce an empty `TokenStream` if no calls were made, + // and omit the final token otherwise. + let mut cursor_snapshot = self.cursor_snapshot.clone(); + let tokens = + std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1)) + .chain((0..self.num_calls).map(|_| { + let token = if cursor_snapshot.desugar_doc_comments { + cursor_snapshot.next_desugared() + } else { + cursor_snapshot.next() + }; + (FlatToken::Token(token.0), token.1) + })) + .take(self.num_calls); + + if !self.replace_ranges.is_empty() { + let mut tokens: Vec<_> = tokens.collect(); + let mut replace_ranges = self.replace_ranges.clone(); + replace_ranges.sort_by_key(|(range, _)| range.start); + + #[cfg(debug_assertions)] + { + for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() { + assert!( + range.end <= next_range.start || range.end >= next_range.end, + "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", + range, + tokens, + next_range, + next_tokens, + ); + } + } + + // Process the replace ranges, starting from the highest start + // position and working our way back. If have tokens like: + // + // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }` + // + // Then we will generate replace ranges for both + // the `#[cfg(FALSE)] field: bool` and the entire + // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }` + // + // By starting processing from the replace range with the greatest + // start position, we ensure that any replace range which encloses + // another replace range will capture the *replaced* tokens for the inner + // range, not the original tokens. + for (range, new_tokens) in replace_ranges.iter().rev() { + assert!(!range.is_empty(), "Cannot replace an empty range: {:?}", range); + // Replace ranges are only allowed to decrease the number of tokens. + assert!( + range.len() >= new_tokens.len(), + "Range {:?} has greater len than {:?}", + range, + new_tokens + ); + + // Replace any removed tokens with `FlatToken::Empty`. + // This keeps the total length of `tokens` constant throughout the + // replacement process, allowing us to use all of the `ReplaceRanges` entries + // without adjusting indices. + let filler = std::iter::repeat((FlatToken::Empty, Spacing::Alone)) + .take(range.len() - new_tokens.len()); + + tokens.splice( + (range.start as usize)..(range.end as usize), + new_tokens.clone().into_iter().chain(filler), + ); + } + make_token_stream(tokens.into_iter(), self.break_last_token) + } else { + make_token_stream(tokens, self.break_last_token) + } + } } impl<'a> Parser<'a> { @@ -65,81 +202,195 @@ force_collect: ForceCollect, f: impl FnOnce(&mut Self, Vec) -> PResult<'a, (R, TrailingToken)>, ) -> PResult<'a, R> { - if matches!(force_collect, ForceCollect::No) && !attr::maybe_needs_tokens(&attrs.attrs) { - return Ok(f(self, attrs.attrs)?.0); + // We only bail out when nothing could possibly observe the collected tokens: + // 1. We cannot be force collecting tokens (since force-collecting requires tokens + // by definition + if matches!(force_collect, ForceCollect::No) + // None of our outer attributes can require tokens (e.g. a proc-macro) + && !attrs.maybe_needs_tokens() + // If our target supports custom inner attributes, then we cannot bail + // out early, since we may need to capture tokens for a custom inner attribute + // invocation. + && !R::SUPPORTS_CUSTOM_INNER_ATTRS + // Never bail out early in `capture_cfg` mode, since there might be `#[cfg]` + // or `#[cfg_attr]` attributes. + && !self.capture_cfg + { + return Ok(f(self, attrs.attrs.into())?.0); } + let start_token = (self.token.clone(), self.token_spacing); let cursor_snapshot = self.token_cursor.clone(); - let (mut ret, trailing_token) = f(self, attrs.attrs)?; - let tokens = match ret.tokens_mut() { - Some(tokens) if tokens.is_none() => tokens, - _ => return Ok(ret), - }; + let has_outer_attrs = !attrs.attrs.is_empty(); + let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes); + let replace_ranges_start = self.capture_state.replace_ranges.len(); + + let ret = f(self, attrs.attrs.into()); + + self.capture_state.capturing = prev_capturing; + + let (mut ret, trailing) = ret?; - // Produces a `TokenStream` on-demand. Using `cursor_snapshot` - // and `num_calls`, we can reconstruct the `TokenStream` seen - // by the callback. This allows us to avoid producing a `TokenStream` - // if it is never needed - for example, a captured `macro_rules!` - // argument that is never passed to a proc macro. - // In practice token stream creation happens rarely compared to - // calls to `collect_tokens` (see some statistics in #78736), - // so we are doing as little up-front work as possible. - // - // This also makes `Parser` very cheap to clone, since - // there is no intermediate collection buffer to clone. - #[derive(Clone)] - struct LazyTokenStreamImpl { - start_token: (Token, Spacing), - cursor_snapshot: TokenCursor, - num_calls: usize, - desugar_doc_comments: bool, - append_unglued_token: Option, - } - impl CreateTokenStream for LazyTokenStreamImpl { - fn create_token_stream(&self) -> TokenStream { - // The token produced by the final call to `next` or `next_desugared` - // was not actually consumed by the callback. The combination - // of chaining the initial token and using `take` produces the desired - // result - we produce an empty `TokenStream` if no calls were made, - // and omit the final token otherwise. - let mut cursor_snapshot = self.cursor_snapshot.clone(); - let tokens = std::iter::once(self.start_token.clone()) - .chain((0..self.num_calls).map(|_| { - if self.desugar_doc_comments { - cursor_snapshot.next_desugared() - } else { - cursor_snapshot.next() - } - })) - .take(self.num_calls); + // When we're not in `capture-cfg` mode, then bail out early if: + // 1. Our target doesn't support tokens at all (e.g we're parsing an `NtIdent`) + // so there's nothing for us to do. + // 2. Our target already has tokens set (e.g. we've parsed something + // like `#[my_attr] $item`. The actual parsing code takes care of prepending + // any attributes to the nonterminal, so we don't need to modify the + // already captured tokens. + // Note that this check is independent of `force_collect`- if we already + // have tokens, or can't even store them, then there's never a need to + // force collection of new tokens. + if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) { + return Ok(ret); + } + + // This is very similar to the bail out check at the start of this function. + // Now that we've parsed an AST node, we have more information available. + if matches!(force_collect, ForceCollect::No) + // We now have inner attributes available, so this check is more precise + // than `attrs.maybe_needs_tokens()` at the start of the function. + // As a result, we don't need to check `R::SUPPORTS_CUSTOM_INNER_ATTRS` + && !crate::parser::attr::maybe_needs_tokens(ret.attrs()) + // Subtle: We call `has_cfg_or_cfg_attr` with the attrs from `ret`. + // This ensures that we consider inner attributes (e.g. `#![cfg]`), + // which require us to have tokens available + // We also call `has_cfg_or_cfg_attr` at the beginning of this function, + // but we only bail out if there's no possibility of inner attributes + // (!R::SUPPORTS_CUSTOM_INNER_ATTRS) + // We only catpure about `#[cfg]` or `#[cfg_attr]` in `capture_cfg` + // mode - during normal parsing, we don't need any special capturing + // for those attributes, since they're builtin. + && !(self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs())) + { + return Ok(ret); + } - make_token_stream(tokens, self.append_unglued_token.clone()) + let mut inner_attr_replace_ranges = Vec::new(); + // Take the captured ranges for any inner attributes that we parsed. + for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) { + if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) { + inner_attr_replace_ranges.push(attr_range); + } else { + self.sess + .span_diagnostic + .delay_span_bug(inner_attr.span, "Missing token range for attribute"); } } - let mut num_calls = self.token_cursor.num_next_calls - cursor_snapshot.num_next_calls; - match trailing_token { + let replace_ranges_end = self.capture_state.replace_ranges.len(); + + let cursor_snapshot_next_calls = cursor_snapshot.num_next_calls; + let mut end_pos = self.token_cursor.num_next_calls; + + // Capture a trailing token if requested by the callback 'f' + match trailing { TrailingToken::None => {} TrailingToken::Semi => { assert_eq!(self.token.kind, token::Semi); - num_calls += 1; + end_pos += 1; } TrailingToken::MaybeComma => { if self.token.kind == token::Comma { - num_calls += 1; + end_pos += 1; } } } - *tokens = Some(LazyTokenStream::new(LazyTokenStreamImpl { + // If we 'broke' the last token (e.g. breaking a '>>' token to two '>' tokens), + // then extend the range of captured tokens to include it, since the parser + // was not actually bumped past it. When the `LazyTokenStream` gets converted + // into a `AttrAnnotatedTokenStream`, we will create the proper token. + if self.token_cursor.break_last_token { + assert_eq!( + trailing, + TrailingToken::None, + "Cannot set `break_last_token` and have trailing token" + ); + end_pos += 1; + } + + let num_calls = end_pos - cursor_snapshot_next_calls; + + // If we have no attributes, then we will never need to + // use any replace ranges. + let replace_ranges: Box<[ReplaceRange]> = if ret.attrs().is_empty() && !self.capture_cfg { + Box::new([]) + } else { + // Grab any replace ranges that occur *inside* the current AST node. + // We will perform the actual replacement when we convert the `LazyTokenStream` + // to a `AttrAnnotatedTokenStream` + let start_calls: u32 = cursor_snapshot_next_calls.try_into().unwrap(); + self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] + .iter() + .cloned() + .chain(inner_attr_replace_ranges.clone().into_iter()) + .map(|(range, tokens)| { + ((range.start - start_calls)..(range.end - start_calls), tokens) + }) + .collect() + }; + + let tokens = LazyTokenStream::new(LazyTokenStreamImpl { start_token, num_calls, cursor_snapshot, - desugar_doc_comments: self.desugar_doc_comments, - append_unglued_token: self.token_cursor.append_unglued_token.clone(), - })); + break_last_token: self.token_cursor.break_last_token, + replace_ranges, + }); + + // If we support tokens at all + if let Some(target_tokens) = ret.tokens_mut() { + if let Some(target_tokens) = target_tokens { + assert!( + !self.capture_cfg, + "Encountered existing tokens with capture_cfg set: {:?}", + target_tokens + ); + } else { + // Store se our newly captured tokens into the AST node + *target_tokens = Some(tokens.clone()); + }; + } + let final_attrs = ret.attrs(); + + // If `capture_cfg` is set and we're inside a recursive call to + // `collect_tokens_trailing_token`, then we need to register a replace range + // if we have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager cfg-expansion + // on the captured token stream. + if self.capture_cfg + && matches!(self.capture_state.capturing, Capturing::Yes) + && has_cfg_or_cfg_attr(&final_attrs) + { + let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens }; + + // Replace the entire AST node that we just parsed, including attributes, + // with a `FlatToken::AttrTarget`. If this AST node is inside an item + // that has `#[derive]`, then this will allow us to cfg-expand this + // AST node. + let start_pos = + if has_outer_attrs { attrs.start_pos } else { cursor_snapshot_next_calls }; + let new_tokens = vec![(FlatToken::AttrTarget(attr_data), Spacing::Alone)]; + + assert!( + !self.token_cursor.break_last_token, + "Should not have unglued last token with cfg attr" + ); + let range: Range = (start_pos.try_into().unwrap())..(end_pos.try_into().unwrap()); + self.capture_state.replace_ranges.push((range, new_tokens)); + self.capture_state.replace_ranges.extend(inner_attr_replace_ranges); + } + + // Only clear our `replace_ranges` when we're finished capturing entirely. + if matches!(self.capture_state.capturing, Capturing::No) { + self.capture_state.replace_ranges.clear(); + // We don't clear `inner_attr_ranges`, as doing so repeatedly + // had a measureable performance impact. Most inner attributes that + // we insert will get removed - when we drop the parser, we'll free + // up the memory used by any attributes that we didn't remove from the map. + } Ok(ret) } } @@ -147,43 +398,112 @@ /// Converts a flattened iterator of tokens (including open and close delimiter tokens) /// into a `TokenStream`, creating a `TokenTree::Delimited` for each matching pair /// of open and close delims. +// FIXME(#67062): Currently, we don't parse `None`-delimited groups correctly, +// which can cause us to end up with mismatched `None` delimiters in our +// captured tokens. This function contains several hacks to work around this - +// essentially, we throw away mismatched `None` delimiters when we encounter them. +// Once we properly parse `None` delimiters, they can be captured just like any +// other tokens, and these hacks can be removed. fn make_token_stream( - tokens: impl Iterator, - append_unglued_token: Option, -) -> TokenStream { + mut iter: impl Iterator, + break_last_token: bool, +) -> AttrAnnotatedTokenStream { #[derive(Debug)] struct FrameData { open: Span, - inner: Vec<(TokenTree, Spacing)>, + open_delim: DelimToken, + inner: Vec<(AttrAnnotatedTokenTree, Spacing)>, } - let mut stack = vec![FrameData { open: DUMMY_SP, inner: vec![] }]; - for (token, spacing) in tokens { + let mut stack = + vec![FrameData { open: DUMMY_SP, open_delim: DelimToken::NoDelim, inner: vec![] }]; + let mut token_and_spacing = iter.next(); + while let Some((token, spacing)) = token_and_spacing { match token { - Token { kind: TokenKind::OpenDelim(_), span } => { - stack.push(FrameData { open: span, inner: vec![] }); + FlatToken::Token(Token { kind: TokenKind::OpenDelim(delim), span }) => { + stack.push(FrameData { open: span, open_delim: delim, inner: vec![] }); } - Token { kind: TokenKind::CloseDelim(delim), span } => { - let frame_data = stack.pop().expect("Token stack was empty!"); + FlatToken::Token(Token { kind: TokenKind::CloseDelim(delim), span }) => { + // HACK: If we enconter a mismatched `None` delimiter at the top + // level, just ignore it. + if matches!(delim, DelimToken::NoDelim) + && (stack.len() == 1 + || !matches!(stack.last_mut().unwrap().open_delim, DelimToken::NoDelim)) + { + token_and_spacing = iter.next(); + continue; + } + let frame_data = stack + .pop() + .unwrap_or_else(|| panic!("Token stack was empty for token: {:?}", token)); + + // HACK: If our current frame has a mismatched opening `None` delimiter, + // merge our current frame with the one above it. That is, transform + // `[ { < first second } third ]` into `[ { first second } third ]` + if !matches!(delim, DelimToken::NoDelim) + && matches!(frame_data.open_delim, DelimToken::NoDelim) + { + stack.last_mut().unwrap().inner.extend(frame_data.inner); + // Process our closing delimiter again, this time at the previous + // frame in the stack + token_and_spacing = Some((token, spacing)); + continue; + } + + assert_eq!( + frame_data.open_delim, delim, + "Mismatched open/close delims: open={:?} close={:?}", + frame_data.open, span + ); let dspan = DelimSpan::from_pair(frame_data.open, span); - let stream = TokenStream::new(frame_data.inner); - let delimited = TokenTree::Delimited(dspan, delim, stream); + let stream = AttrAnnotatedTokenStream::new(frame_data.inner); + let delimited = AttrAnnotatedTokenTree::Delimited(dspan, delim, stream); stack .last_mut() - .unwrap_or_else(|| panic!("Bottom token frame is missing for tokens!")) + .unwrap_or_else(|| { + panic!("Bottom token frame is missing for token: {:?}", token) + }) .inner .push((delimited, Spacing::Alone)); } - token => { - stack - .last_mut() - .expect("Bottom token frame is missing!") - .inner - .push((TokenTree::Token(token), spacing)); - } + FlatToken::Token(token) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((AttrAnnotatedTokenTree::Token(token), spacing)), + FlatToken::AttrTarget(data) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((AttrAnnotatedTokenTree::Attributes(data), spacing)), + FlatToken::Empty => {} } + token_and_spacing = iter.next(); + } + // HACK: If we don't have a closing `None` delimiter for our last + // frame, merge the frame with the top-level frame. That is, + // turn `< first second` into `first second` + if stack.len() == 2 && stack[1].open_delim == DelimToken::NoDelim { + let temp_buf = stack.pop().unwrap(); + stack.last_mut().unwrap().inner.extend(temp_buf.inner); } let mut final_buf = stack.pop().expect("Missing final buf!"); - final_buf.inner.extend(append_unglued_token); + if break_last_token { + let (last_token, spacing) = final_buf.inner.pop().unwrap(); + if let AttrAnnotatedTokenTree::Token(last_token) = last_token { + let unglued_first = last_token.kind.break_two_token_op().unwrap().0; + + // A 'unglued' token is always two ASCII characters + let mut first_span = last_token.span.shrink_to_lo(); + first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1)); + + final_buf.inner.push(( + AttrAnnotatedTokenTree::Token(Token::new(unglued_first, first_span)), + spacing, + )); + } else { + panic!("Unexpected last token {:?}", last_token) + } + } assert!(stack.is_empty(), "Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack); - TokenStream::new(final_buf.inner) + AttrAnnotatedTokenStream::new(final_buf.inner) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/diagnostics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/diagnostics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/diagnostics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/diagnostics.rs 2021-06-17 03:53:50.000000000 +0000 @@ -666,21 +666,23 @@ ); match x { Ok((_, _, false)) => { - self.bump(); // `>` - match self.parse_expr() { - Ok(_) => { - e.span_suggestion_verbose( - binop.span.shrink_to_lo(), - TURBOFISH_SUGGESTION_STR, - "::".to_string(), - Applicability::MaybeIncorrect, - ); - e.emit(); - *expr = self.mk_expr_err(expr.span.to(self.prev_token.span)); - return Ok(()); - } - Err(mut err) => { - err.cancel(); + if self.eat(&token::Gt) { + match self.parse_expr() { + Ok(_) => { + e.span_suggestion_verbose( + binop.span.shrink_to_lo(), + TURBOFISH_SUGGESTION_STR, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + e.emit(); + *expr = + self.mk_expr_err(expr.span.to(self.prev_token.span)); + return Ok(()); + } + Err(mut err) => { + err.cancel(); + } } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/expr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/expr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/expr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/expr.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,4 @@ -use super::pat::{GateOr, RecoverComma, PARAM_EXPECTED}; +use super::pat::{RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken}; @@ -92,7 +92,22 @@ self.parse_expr_res(Restrictions::empty(), None) } - pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> { + /// Parses an expression, forcing tokens to be collected + pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P> { + // If we have outer attributes, then the call to `collect_tokens_trailing_token` + // will be made for us. + if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) { + self.parse_expr() + } else { + // If we don't have outer attributes, then we need to ensure + // that collection happens by using `collect_tokens_no_attrs`. + // Expression don't support custom inner attributes, so `parse_expr` + // will never try to collect tokens if we don't have outer attributes. + self.collect_tokens_no_attrs(|this| this.parse_expr()) + } + } + + pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> { self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) } @@ -1803,7 +1818,7 @@ /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; self.expect(&token::Eq)?; let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) @@ -1866,7 +1881,7 @@ _ => None, }; - let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; if !self.eat_keyword(kw::In) { self.error_missing_in_for_loop(); } @@ -2073,7 +2088,7 @@ let attrs = self.parse_outer_attributes()?; self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; - let pat = this.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?; + let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; let cond = this.parse_expr()?; @@ -2566,19 +2581,17 @@ attrs: AttrWrapper, f: impl FnOnce(&mut Self, Vec) -> PResult<'a, P>, ) -> PResult<'a, P> { - // FIXME - come up with a nice way to properly forward `ForceCollect`from - // the nonterminal parsing code. TThis approach iscorrect, but will cause - // us to unnecessarily capture tokens for exprs that have only builtin - // attributes. Revisit this before #![feature(stmt_expr_attributes)] is stabilized - let force_collect = if attrs.is_empty() { ForceCollect::No } else { ForceCollect::Yes }; - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR) && this.token.kind == token::Semi { TrailingToken::Semi } else { - TrailingToken::None + // FIXME - pass this through from the place where we know + // we need a comma, rather than assuming that `#[attr] expr,` + // always captures a trailing comma + TrailingToken::MaybeComma }; Ok((res, trailing)) }) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/item.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/item.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/item.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/item.rs 2021-06-17 03:53:50.000000000 +0000 @@ -103,20 +103,11 @@ // over when we bump the parser if let token::Interpolated(nt) = &self.token.kind { if let token::NtItem(item) = &**nt { - let item = item.clone(); + let mut item = item.clone(); + self.bump(); - return self.collect_tokens_trailing_token( - attrs, - force_collect, - |this, mut attrs| { - let mut item = item; - mem::swap(&mut item.attrs, &mut attrs); - item.attrs.extend(attrs); - // Bump the parser so the we capture the token::Interpolated - this.bump(); - Ok((Some(item.into_inner()), TrailingToken::None)) - }, - ); + attrs.prepend_to_nt_inner(&mut item.attrs); + return Ok(Some(item.into_inner())); } }; @@ -530,7 +521,7 @@ generics.where_clause = self.parse_where_clause()?; - let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item())?; + let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?; let item_kind = match ty_second { Some(ty_second) => { @@ -718,22 +709,32 @@ } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let items = self.parse_item_list(attrs, |p| p.parse_trait_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; Ok((ident, ItemKind::Trait(box TraitKind(is_auto, unsafety, tps, bounds, items)))) } } - pub fn parse_impl_item(&mut self) -> PResult<'a, Option>>> { - self.parse_assoc_item(|_| true) + pub fn parse_impl_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + self.parse_assoc_item(|_| true, force_collect) } - pub fn parse_trait_item(&mut self) -> PResult<'a, Option>>> { - self.parse_assoc_item(|edition| edition >= Edition::Edition2018) + pub fn parse_trait_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + self.parse_assoc_item(|edition| edition >= Edition::Edition2018, force_collect) } /// Parses associated items. - fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { - Ok(self.parse_item_(req_name, ForceCollect::No)?.map( + fn parse_assoc_item( + &mut self, + req_name: ReqName, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + Ok(self.parse_item_(req_name, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, @@ -918,14 +919,17 @@ unsafety: Unsafe, ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?; let module = ast::ForeignMod { unsafety, abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). - pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { - Ok(self.parse_item_(|_| true, ForceCollect::No)?.map( + pub fn parse_foreign_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + Ok(self.parse_item_(|_| true, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, @@ -1444,7 +1448,7 @@ Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } - /// Is this unambiguously the start of a `macro_rules! foo` item defnition? + /// Is this unambiguously the start of a `macro_rules! foo` item definition? fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(kw::MacroRules) && self.look_ahead(1, |t| *t == token::Not) @@ -1474,7 +1478,15 @@ let vstr = pprust::vis_to_string(vis); let vstr = vstr.trim_end(); if macro_rules { - self.sess.gated_spans.gate(sym::pub_macro_rules, vis.span); + let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); + self.struct_span_err(vis.span, &msg) + .span_suggestion( + vis.span, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect, // speculative + ) + .emit(); } else { self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") .span_suggestion( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -14,18 +14,21 @@ pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; use diagnostics::Error; -pub use pat::{GateOr, RecoverComma}; +pub use pat::RecoverComma; pub use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{self, DelimToken, Token, TokenKind}; +use rustc_ast::tokenstream::AttributesData; use rustc_ast::tokenstream::{self, DelimSpan, Spacing}; -use rustc_ast::tokenstream::{TokenStream, TokenTree, TreeAndSpacing}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::AttrId; use rustc_ast::DUMMY_NODE_ID; use rustc_ast::{self as ast, AnonConst, AstLike, AttrStyle, AttrVec, Const, CrateSugar, Extern}; use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit, Unsafe}; use rustc_ast::{Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; @@ -34,6 +37,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use tracing::debug; +use std::ops::Range; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -64,6 +68,7 @@ No, } +#[derive(Debug, Eq, PartialEq)] pub enum TrailingToken { None, Semi, @@ -111,6 +116,7 @@ pub token_spacing: Spacing, /// The previous token. pub prev_token: Token, + pub capture_cfg: bool, restrictions: Restrictions, expected_tokens: Vec, // Important: This must only be advanced from `next_tok` @@ -134,6 +140,44 @@ pub last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. subparser_name: Option<&'static str>, + capture_state: CaptureState, +} + +/// Indicates a range of tokens that should be replaced by +/// the tokens in the provided vector. This is used in two +/// places during token collection: +/// +/// 1. During the parsing of an AST node that may have a `#[derive]` +/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` +/// In this case, we use a `ReplaceRange` to replace the entire inner AST node +/// with `FlatToken::AttrTarget`, allowing us to perform eager cfg-expansion +/// on a `AttrAnnotatedTokenStream` +/// +/// 2. When we parse an inner attribute while collecting tokens. We +/// remove inner attributes from the token stream entirely, and +/// instead track them through the `attrs` field on the AST node. +/// This allows us to easily manipulate them (for example, removing +/// the first macro inner attribute to invoke a proc-macro). +/// When create a `TokenStream`, the inner attributes get inserted +/// into the proper place in the token stream. +pub type ReplaceRange = (Range, Vec<(FlatToken, Spacing)>); + +/// Controls how we capture tokens. Capturing can be expensive, +/// so we try to avoid performing capturing in cases where +/// we will never need a `AttrAnnotatedTokenStream` +#[derive(Copy, Clone)] +pub enum Capturing { + /// We aren't performing any capturing - this is the default mode. + No, + /// We are capturing tokens + Yes, +} + +#[derive(Clone)] +struct CaptureState { + capturing: Capturing, + replace_ranges: Vec, + inner_attr_ranges: FxHashMap, } impl<'a> Drop for Parser<'a> { @@ -167,11 +211,11 @@ // want to capture just the first 'unglued' token. // For example, capturing the `Vec` // in `Option>` requires us to unglue - // the trailing `>>` token. The `append_unglued_token` + // the trailing `>>` token. The `break_last_token` // field is used to track this token - it gets // appended to the captured stream when // we evaluate a `LazyTokenStream` - append_unglued_token: Option, + break_last_token: bool, } #[derive(Clone)] @@ -188,9 +232,9 @@ TokenCursorFrame { delim, span, - open_delim: delim == token::NoDelim, + open_delim: false, tree_cursor: tts.into_trees(), - close_delim: delim == token::NoDelim, + close_delim: false, } } } @@ -364,19 +408,24 @@ desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { + let mut start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens); + start_frame.open_delim = true; + start_frame.close_delim = true; + let mut parser = Parser { sess, token: Token::dummy(), token_spacing: Spacing::Alone, prev_token: Token::dummy(), + capture_cfg: false, restrictions: Restrictions::empty(), expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens), + frame: start_frame, stack: Vec::new(), num_next_calls: 0, desugar_doc_comments, - append_unglued_token: None, + break_last_token: false, }, desugar_doc_comments, unmatched_angle_bracket_count: 0, @@ -385,6 +434,11 @@ last_unexpected_token_span: None, last_type_ascription: None, subparser_name, + capture_state: CaptureState { + capturing: Capturing::No, + replace_ranges: Vec::new(), + inner_attr_ranges: Default::default(), + }, }; // Make parser point to the first token. @@ -394,21 +448,29 @@ } fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) { - let (mut next, spacing) = if self.desugar_doc_comments { - self.token_cursor.next_desugared() - } else { - self.token_cursor.next() - }; - self.token_cursor.num_next_calls += 1; - // We've retrieved an token from the underlying - // cursor, so we no longer need to worry about - // an unglued token. See `break_and_eat` for more details - self.token_cursor.append_unglued_token = None; - if next.span.is_dummy() { - // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = fallback_span.with_ctxt(next.span.ctxt()); + loop { + let (mut next, spacing) = if self.desugar_doc_comments { + self.token_cursor.next_desugared() + } else { + self.token_cursor.next() + }; + self.token_cursor.num_next_calls += 1; + // We've retrieved an token from the underlying + // cursor, so we no longer need to worry about + // an unglued token. See `break_and_eat` for more details + self.token_cursor.break_last_token = false; + if next.span.is_dummy() { + // Tweak the location for better diagnostics, but keep syntactic context intact. + next.span = fallback_span.with_ctxt(next.span.ctxt()); + } + if matches!( + next.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + ) { + continue; + } + return (next, spacing); } - (next, spacing) } pub fn unexpected(&mut self) -> PResult<'a, T> { @@ -606,8 +668,7 @@ // If we consume any additional tokens, then this token // is not needed (we'll capture the entire 'glued' token), // and `next_tok` will set this field to `None` - self.token_cursor.append_unglued_token = - Some((TokenTree::Token(self.token.clone()), Spacing::Alone)); + self.token_cursor.break_last_token = true; // Use the spacing of the glued token as the spacing // of the unglued second token. self.bump_with((Token::new(second, second_span), self.token_spacing)); @@ -688,6 +749,8 @@ let mut recovered = false; let mut trailing = false; let mut v = vec![]; + let unclosed_delims = !self.unclosed_delims.is_empty(); + while !self.expect_any_with_type(kets, expect) { if let token::CloseDelim(..) | token::Eof = self.token.kind { break; @@ -708,7 +771,7 @@ // Attempt to keep parsing if it was a similar separator. if let Some(ref tokens) = t.similar_tokens() { - if tokens.contains(&self.token.kind) { + if tokens.contains(&self.token.kind) && !unclosed_delims { self.bump(); } } @@ -867,15 +930,38 @@ } let frame = &self.token_cursor.frame; - match frame.tree_cursor.look_ahead(dist - 1) { - Some(tree) => match tree { - TokenTree::Token(token) => looker(token), - TokenTree::Delimited(dspan, delim, _) => { - looker(&Token::new(token::OpenDelim(*delim), dspan.open)) - } - }, - None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)), + if frame.delim != DelimToken::NoDelim { + let all_normal = (0..dist).all(|i| { + let token = frame.tree_cursor.look_ahead(i); + !matches!(token, Some(TokenTree::Delimited(_, DelimToken::NoDelim, _))) + }); + if all_normal { + return match frame.tree_cursor.look_ahead(dist - 1) { + Some(tree) => match tree { + TokenTree::Token(token) => looker(token), + TokenTree::Delimited(dspan, delim, _) => { + looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + } + }, + None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)), + }; + } } + + let mut cursor = self.token_cursor.clone(); + let mut i = 0; + let mut token = Token::dummy(); + while i < dist { + token = cursor.next().0; + if matches!( + token.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + ) { + continue; + } + i += 1; + } + return looker(&token); } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. @@ -987,12 +1073,15 @@ } // Collect tokens because they are used during lowering to HIR. - let expr = self.collect_tokens_no_attrs(|this| this.parse_expr())?; + let expr = self.parse_expr_force_collect()?; let span = expr.span; match &expr.kind { - // Not gated to supporte things like `doc = $expr` that work on stable. - _ if is_interpolated_expr => {} + // Not gated to support things like `doc = $expr` that work on stable. + // Do not gate in `capture_cfg` mode, since we flatten all nontemrinals + // before parsing. `capture_cfg` mode is only used to reparse existing + // tokens, so the gating will be performed by the initial parse + _ if is_interpolated_expr || self.capture_cfg => {} ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {} _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span), } @@ -1287,3 +1376,24 @@ } } } + +/// A helper struct used when building a `AttrAnnotatedTokenStream` from +/// a `LazyTokenStream`. Both delimiter and non-delimited tokens +/// are stored as `FlatToken::Token`. A vector of `FlatToken`s +/// is then 'parsed' to build up a `AttrAnnotatedTokenStream` with nested +/// `AttrAnnotatedTokenTree::Delimited` tokens +#[derive(Debug, Clone)] +pub enum FlatToken { + /// A token - this holds both delimiter (e.g. '{' and '}') + /// and non-delimiter tokens + Token(Token), + /// Holds the `AttributesData` for an AST node. The + /// `AttributesData` is inserted directly into the + /// constructed `AttrAnnotatedTokenStream` as + /// a `AttrAnnotatedTokenTree::Attributes` + AttrTarget(AttributesData), + /// A special 'empty' token that is ignored during the conversion + /// to a `AttrAnnotatedTokenStream`. This is used to simplify the + /// handling of replace ranges. + Empty, +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/nonterminal.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/nonterminal.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/nonterminal.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/nonterminal.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,7 +4,7 @@ use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; -use crate::parser::pat::{GateOr, RecoverComma}; +use crate::parser::pat::RecoverComma; use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle}; impl<'a> Parser<'a> { @@ -61,7 +61,8 @@ }, _ => false, }, - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => match token.kind { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { + match token.kind { token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) token::OpenDelim(token::Paren) | // tuple pattern token::OpenDelim(token::Bracket) | // slice pattern @@ -75,10 +76,11 @@ token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::Pat2021 {..}), + token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), token::Interpolated(ref nt) => may_be_ident(nt), _ => false, - }, + } + } NonterminalKind::Lifetime => match token.kind { token::Lifetime(_) => true, token::Interpolated(ref nt) => { @@ -118,32 +120,17 @@ return Err(self.struct_span_err(self.token.span, "expected a statement")); } }, - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { token::NtPat(self.collect_tokens_no_attrs(|this| match kind { - NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None), - NonterminalKind::Pat2021 { .. } => { - this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) + NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None), + NonterminalKind::PatWithOr { .. } => { + this.parse_pat_allow_top_alt(None, RecoverComma::No) } _ => unreachable!(), })?) } - // If there are attributes present, then `parse_expr` will end up collecting tokens, - // turning the outer `collect_tokens_no_attrs` into a no-op due to the already present - // tokens. If there are *not* attributes present, then the outer - // `collect_tokens_no_attrs` will ensure that we will end up collecting tokens for the - // expressions. - // - // This is less efficient than it could be, since the outer `collect_tokens_no_attrs` - // still needs to snapshot the `TokenCursor` before calling `parse_expr`, even when - // `parse_expr` will end up collecting tokens. Ideally, this would work more like - // `parse_item`, and take in a `ForceCollect` parameter. However, this would require - // adding a `ForceCollect` parameter in a bunch of places in expression parsing - // for little gain. If the perf impact from this turns out to be noticeable, we should - // revisit this apporach. - NonterminalKind::Expr => { - token::NtExpr(self.collect_tokens_no_attrs(|this| this.parse_expr())?) - } + NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes token::NtLiteral( @@ -168,9 +155,7 @@ NonterminalKind::Path => token::NtPath( self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, ), - NonterminalKind::Meta => { - token::NtMeta(P(self.collect_tokens_no_attrs(|this| this.parse_attr_item(false))?)) - } + NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::TT => token::NtTT(self.parse_token_tree()), NonterminalKind::Vis => token::NtVis( self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/pat.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/pat.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/pat.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/pat.rs 2021-06-17 03:53:50.000000000 +0000 @@ -17,13 +17,6 @@ const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here"; -/// Whether or not an or-pattern should be gated when occurring in the current context. -#[derive(PartialEq, Clone, Copy)] -pub enum GateOr { - Yes, - No, -} - /// Whether or not to recover a `,` when parsing or-patterns. #[derive(PartialEq, Copy, Clone)] pub enum RecoverComma { @@ -64,10 +57,9 @@ pub fn parse_pat_allow_top_alt( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, P> { - self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat) + self.parse_pat_allow_top_alt_inner(expected, rc).map(|(pat, _)| pat) } /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = @@ -75,7 +67,6 @@ fn parse_pat_allow_top_alt_inner( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, (P, bool)> { // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated @@ -90,7 +81,7 @@ // Parse the first pattern (`p_0`). let first_pat = self.parse_pat_no_top_alt(expected)?; - self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?; + self.maybe_recover_unexpected_comma(first_pat.span, rc)?; // If the next token is not a `|`, // this is not an or-pattern and we should exit here. @@ -99,10 +90,6 @@ // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. if let Some(leading_vert_span) = leading_vert_span { - if gate_or == GateOr::Yes && self.sess.gated_spans.is_ungated(sym::or_patterns) { - self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span); - } - // If there was a leading vert, treat this as an or-pattern. This improves // diagnostics. let span = leading_vert_span.to(self.prev_token.span); @@ -128,16 +115,11 @@ err.span_label(lo, WHILE_PARSING_OR_MSG); err })?; - self.maybe_recover_unexpected_comma(pat.span, rc, gate_or)?; + self.maybe_recover_unexpected_comma(pat.span, rc)?; pats.push(pat); } let or_pattern_span = lo.to(self.prev_token.span); - // Feature gate the or-pattern if instructed: - if gate_or == GateOr::Yes { - self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span); - } - Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert)) } @@ -152,14 +134,13 @@ pub(super) fn parse_pat_before_ty( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, syntax_loc: &str, ) -> PResult<'a, (P, bool)> { // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level // or-patterns so that we can detect when a user tries to use it. This allows us to print a // better error message. - let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, gate_or, rc)?; + let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, rc)?; let colon = self.eat(&token::Colon); if let PatKind::Or(pats) = &pat.kind { @@ -213,12 +194,7 @@ self.bump(); } - self.parse_pat_before_ty( - PARAM_EXPECTED, - GateOr::No, - RecoverComma::No, - "function parameters", - ) + self.parse_pat_before_ty(PARAM_EXPECTED, RecoverComma::No, "function parameters") } /// Eat the or-pattern `|` separator. @@ -287,12 +263,7 @@ /// 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, - gate_or: GateOr, - ) -> PResult<'a, ()> { + fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> { if rc == RecoverComma::No || self.token != token::Comma { return Ok(()); } @@ -313,22 +284,18 @@ if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { const MSG: &str = "try adding parentheses to match on a tuple..."; - let or_suggestion = - gate_or == GateOr::No || !self.sess.gated_spans.is_ungated(sym::or_patterns); err.span_suggestion( seq_span, - if or_suggestion { MSG } else { MSG.trim_end_matches('.') }, + MSG, format!("({})", seq_snippet), Applicability::MachineApplicable, ); - if or_suggestion { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(",", " |"), - Applicability::MachineApplicable, - ); - } + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(",", " |"), + Applicability::MachineApplicable, + ); } Err(err) } @@ -383,7 +350,7 @@ } else if self.check(&token::OpenDelim(token::Bracket)) { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| { - p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) + p.parse_pat_allow_top_alt(None, RecoverComma::No) })?; PatKind::Slice(pats) } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { @@ -596,9 +563,8 @@ /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { - let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) - })?; + let (fields, trailing_comma) = + self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. @@ -911,9 +877,8 @@ if qself.is_some() { return self.error_qpath_before_pat(&path, "("); } - let (fields, _) = self.parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) - })?; + let (fields, _) = + self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -1079,7 +1044,7 @@ // Parsing a pattern of the form `fieldname: pat`. let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No)?; hi = pat.span; (pat, fieldname, false) } else { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/stmt.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/stmt.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse/src/parser/stmt.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse/src/parser/stmt.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; use super::diagnostics::{AttemptLocalParseRecovery, Error}; use super::expr::LhsExpr; -use super::pat::{GateOr, RecoverComma}; +use super::pat::RecoverComma; use super::path::PathStyle; use super::TrailingToken; use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode}; @@ -48,39 +48,26 @@ if let token::Interpolated(nt) = &self.token.kind { if let token::NtStmt(stmt) = &**nt { let mut stmt = stmt.clone(); - return self.collect_tokens_trailing_token( - attrs, - force_collect, - |this, mut attrs| { - stmt.visit_attrs(|stmt_attrs| { - mem::swap(stmt_attrs, &mut attrs); - stmt_attrs.extend(attrs); - }); - // Make sure we capture the token::Interpolated - this.bump(); - Ok((Some(stmt), TrailingToken::None)) - }, - ); + self.bump(); + stmt.visit_attrs(|stmt_attrs| { + attrs.prepend_to_nt_inner(stmt_attrs); + }); + return Ok(Some(stmt)); } } Ok(Some(if self.token.is_keyword(kw::Let) { self.parse_local_mk(lo, attrs, capture_semi, force_collect)? } else if self.is_kw_followed_by_ident(kw::Mut) { - self.recover_stmt_local( - lo, - attrs.take_for_recovery().into(), - "missing keyword", - "let mut", - )? + self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")? } else if self.is_kw_followed_by_ident(kw::Auto) { self.bump(); // `auto` let msg = "write `let` instead of `auto` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.take_for_recovery().into(), msg, "let")? + self.recover_stmt_local(lo, attrs, msg, "let")? } else if self.is_kw_followed_by_ident(sym::var) { self.bump(); // `var` let msg = "write `let` instead of `var` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.take_for_recovery().into(), msg, "let")? + self.recover_stmt_local(lo, attrs, msg, "let")? } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something @@ -112,7 +99,7 @@ attrs: AttrWrapper, force_collect: ForceCollect, ) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { let path = this.parse_path(PathStyle::Expr)?; if this.eat(&token::Not) { @@ -132,14 +119,22 @@ }; let expr = this.with_res(Restrictions::STMT_EXPR, |this| { - let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs)?; + this.parse_dot_or_call_expr_with(expr, lo, attrs) + })?; + // `DUMMY_SP` will get overwritten later in this function + Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None)) + })?; + + if let StmtKind::Expr(expr) = stmt.kind { + // Perform this outside of the `collect_tokens_trailing_token` closure, + // since our outer attributes do not apply to this part of the expression + let expr = self.with_res(Restrictions::STMT_EXPR, |this| { this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) })?; - Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Expr(expr)), - TrailingToken::None, - )) - }) + Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) + } else { + Ok(stmt) + } } /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`. @@ -183,7 +178,7 @@ fn recover_stmt_local( &mut self, lo: Span, - attrs: AttrVec, + attrs: AttrWrapper, msg: &str, sugg: &str, ) -> PResult<'a, Stmt> { @@ -213,16 +208,21 @@ }) } - fn recover_local_after_let(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> { - let local = self.parse_local(attrs)?; - Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local))) + fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { + self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + let local = this.parse_local(attrs.into())?; + // FIXME - maybe capture semicolon in recovery? + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + TrailingToken::None, + )) + }) } /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let (pat, colon) = - self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?; + let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?; let (err, ty) = if colon { // Save the state of the parser before parsing type normally, in case there is a `:` diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse_format/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse_format/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_parse_format/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_parse_format/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,7 +10,7 @@ test(attr(deny(warnings))) )] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(bool_to_option)] pub use Alignment::*; @@ -213,11 +213,13 @@ Some(String(self.string(pos + 1))) } else { let arg = self.argument(); - if let Some(end) = self.must_consume('}') { - let start = self.to_span_index(pos); - let end = self.to_span_index(end + 1); + if let Some(rbrace_byte_idx) = self.must_consume('}') { + let lbrace_inner_offset = self.to_span_index(pos); + let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx); if self.is_literal { - self.arg_places.push(start.to(end)); + self.arg_places.push( + lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)), + ); } } Some(NextArgument(arg)) @@ -735,25 +737,24 @@ }; fn find_skips(snippet: &str, is_raw: bool) -> Vec { - let mut eat_ws = false; let mut s = snippet.char_indices().peekable(); let mut skips = vec![]; while let Some((pos, c)) = s.next() { match (c, s.peek()) { // skip whitespace and empty lines ending in '\\' ('\\', Some((next_pos, '\n'))) if !is_raw => { - eat_ws = true; skips.push(pos); skips.push(*next_pos); let _ = s.next(); - } - ('\\', Some((next_pos, '\n' | 'n' | 't'))) if eat_ws => { - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - (' ' | '\n' | '\t', _) if eat_ws => { - skips.push(pos); + + while let Some((pos, c)) = s.peek() { + if matches!(c, ' ' | '\n' | '\t') { + skips.push(*pos); + let _ = s.next(); + } else { + break; + } + } } ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { skips.push(*next_pos); @@ -804,10 +805,6 @@ } } } - _ if eat_ws => { - // `take_while(|c| c.is_whitespace())` - eat_ws = false; - } _ => {} } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/check_attr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/check_attr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/check_attr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/check_attr.rs 2021-06-17 03:53:50.000000000 +0000 @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_errors::{pluralize, struct_span_err}; +use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -69,49 +69,48 @@ let mut is_valid = true; let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - is_valid &= if self.tcx.sess.check_name(attr, sym::inline) { - self.check_inline(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::non_exhaustive) { - self.check_non_exhaustive(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::marker) { - self.check_marker(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::target_feature) { - self.check_target_feature(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::track_caller) { - self.check_track_caller(hir_id, &attr.span, attrs, span, target) - } else if self.tcx.sess.check_name(attr, sym::doc) { - self.check_doc_attrs(attr, hir_id, target) - } else if self.tcx.sess.check_name(attr, sym::no_link) { - self.check_no_link(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::export_name) { - self.check_export_name(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) { - self.check_rustc_args_required_const(&attr, span, target, item) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_start) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_end) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { - self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) - } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { - self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::naked) { - self.check_naked(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) { - self.check_rustc_legacy_const_generics(&attr, span, target, item) - } else { - // lint-only checks - if self.tcx.sess.check_name(attr, sym::cold) { - self.check_cold(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_name) { - self.check_link_name(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_section) { - self.check_link_section(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::no_mangle) { - self.check_no_mangle(hir_id, attr, span, target); + is_valid &= match attr.name_or_empty() { + sym::inline => self.check_inline(hir_id, attr, span, target), + sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), + sym::marker => self.check_marker(hir_id, attr, span, target), + sym::target_feature => self.check_target_feature(hir_id, attr, span, target), + sym::track_caller => { + self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - true + sym::doc => self.check_doc_attrs(attr, hir_id, target), + sym::no_link => self.check_no_link(hir_id, &attr, span, target), + sym::export_name => self.check_export_name(hir_id, &attr, span, target), + sym::rustc_args_required_const => { + self.check_rustc_args_required_const(&attr, span, target, item) + } + sym::rustc_layout_scalar_valid_range_start + | sym::rustc_layout_scalar_valid_range_end => { + self.check_rustc_layout_scalar_valid_range(&attr, span, target) + } + sym::allow_internal_unstable => { + self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) + } + sym::rustc_allow_const_fn_unstable => { + self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) + } + sym::naked => self.check_naked(hir_id, attr, span, target), + sym::rustc_legacy_const_generics => { + self.check_rustc_legacy_const_generics(&attr, span, target, item) + } + sym::rustc_clean + | sym::rustc_dirty + | sym::rustc_if_this_changed + | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), + _ => true, }; + // lint-only checks + match attr.name_or_empty() { + sym::cold => self.check_cold(hir_id, attr, span, target), + sym::link_name => self.check_link_name(hir_id, attr, span, target), + sym::link_section => self.check_link_section(hir_id, attr, span, target), + sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), + _ => {} + } } if !is_valid { @@ -642,10 +641,10 @@ | sym::masked | sym::no_default_passes | sym::no_inline + | sym::notable_trait | sym::passes | sym::plugins | sym::primitive - | sym::spotlight | sym::test => {} _ => { @@ -654,11 +653,23 @@ hir_id, i_meta.span, |lint| { - let msg = format!( + let mut diag = lint.build(&format!( "unknown `doc` attribute `{}`", rustc_ast_pretty::pprust::path_to_string(&i_meta.path), - ); - lint.build(&msg).emit(); + )); + if i_meta.has_name(sym::spotlight) { + diag.note( + "`doc(spotlight)` was renamed to `doc(notable_trait)`", + ); + diag.span_suggestion_short( + i_meta.span, + "use `notable_trait` instead", + String::from("notable_trait"), + Applicability::MachineApplicable, + ); + diag.note("`doc(spotlight)` is now a no-op"); + } + diag.emit(); }, ); is_valid = false; @@ -1012,6 +1023,20 @@ } } + /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph + /// option is passed to the compiler. + fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool { + if self.tcx.sess.opts.debugging_opts.query_dep_graph { + true + } else { + self.tcx + .sess + .struct_span_err(attr.span, "attribute requires -Z query-dep-graph to be enabled") + .emit(); + false + } + } + /// Checks if `#[link_section]` is applied to a function or static. fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { @@ -1084,7 +1109,7 @@ // ``` let hints: Vec<_> = attrs .iter() - .filter(|attr| self.tcx.sess.check_name(attr, sym::repr)) + .filter(|attr| attr.has_name(sym::repr)) .filter_map(|attr| attr.meta_item_list()) .flatten() .collect(); @@ -1221,7 +1246,7 @@ fn check_used(&self, attrs: &'hir [Attribute], target: Target) { for attr in attrs { - if self.tcx.sess.check_name(attr, sym::used) && target != Target::Static { + if attr.has_name(sym::used) && target != Target::Static { self.tcx .sess .span_err(attr.span, "attribute must be applied to a `static` variable"); @@ -1423,7 +1448,7 @@ sym::path, sym::automatically_derived, sym::start, - sym::main, + sym::rustc_main, ]; for attr in attrs { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/dead.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/dead.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/dead.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/dead.rs 2021-06-17 03:53:50.000000000 +0000 @@ -451,7 +451,9 @@ ) .chain( // Seed entry point - tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)), + tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| { + def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + }), ) .collect::>(); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/entry.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/entry.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/entry.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/entry.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,12 +1,13 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; -use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{CrateType, EntryFnType}; +use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -16,9 +17,6 @@ map: Map<'tcx>, - /// The top-level function called `main`. - main_fn: Option<(HirId, Span)>, - /// The function that has attribute named `main`. attr_main_fn: Option<(HirId, Span)>, @@ -50,7 +48,7 @@ } } -fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> { +fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { assert_eq!(cnum, LOCAL_CRATE); let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); @@ -67,7 +65,6 @@ let mut ctxt = EntryContext { session: tcx.sess, map: tcx.hir(), - main_fn: None, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new(), @@ -84,7 +81,7 @@ let attrs = ctxt.map.attrs(item.hir_id()); if ctxt.session.contains_name(attrs, sym::start) { EntryPointType::Start - } else if ctxt.session.contains_name(attrs, sym::main) { + } else if ctxt.session.contains_name(attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { @@ -111,18 +108,11 @@ if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) { throw_attr_err(&ctxt.session, attr.span, "start"); } - if let Some(attr) = ctxt.session.find_by_name(attrs, sym::main) { - throw_attr_err(&ctxt.session, attr.span, "main"); - } - } - EntryPointType::MainNamed => { - if ctxt.main_fn.is_none() { - ctxt.main_fn = Some((item.hir_id(), item.span)); - } else { - struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions") - .emit(); + if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) { + throw_attr_err(&ctxt.session, attr.span, "rustc_main"); } } + EntryPointType::MainNamed => (), EntryPointType::OtherMain => { ctxt.non_main_fns.push((item.hir_id(), item.span)); } @@ -154,16 +144,23 @@ } } -fn configure_main( - tcx: TyCtxt<'_>, - visitor: &EntryContext<'_, '_>, -) -> Option<(LocalDefId, EntryFnType)> { +fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> { if let Some((hir_id, _)) = visitor.start_fn { - Some((tcx.hir().local_def_id(hir_id), EntryFnType::Start)) + Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Start)) } else if let Some((hir_id, _)) = visitor.attr_main_fn { - Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) - } else if let Some((hir_id, _)) = visitor.main_fn { - Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) + Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main)) + } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) { + if tcx.main_def.unwrap().is_import && !tcx.features().imported_main { + let span = tcx.main_def.unwrap().span; + feature_err( + &tcx.sess.parse_sess, + sym::imported_main, + span, + "using an imported function as entry point `main` is experimental", + ) + .emit(); + } + Some((def_id, EntryFnType::Main)) } else { no_main_err(tcx, visitor); None @@ -171,7 +168,7 @@ } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().item.span; + let sp = tcx.hir().krate().item.inner; if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. @@ -193,10 +190,7 @@ err.span_note(span, "here is a function named `main`"); } err.note("you have one or more functions named `main` not defined at the crate level"); - err.help( - "either move the `main` function definitions or attach the `#[main]` attribute \ - to one of them", - ); + err.help("consider moving the `main` function definitions"); // There were some functions named `main` though. Try to give the user a hint. format!( "the main function must be defined at the crate level{}", @@ -216,6 +210,14 @@ } else { err.note(¬e); } + + if let Some(main_def) = tcx.main_def { + if main_def.opt_fn_def_id().is_none() { + // There is something at `crate::main`, but it is not a function definition. + err.span_label(main_def.span, &format!("non-function item at `crate::main` is found")); + } + } + if tcx.sess.teach(&err.get_code().unwrap()) { err.note( "If you don't know the basics of Rust, you can go look to the Rust Book \ @@ -225,7 +227,7 @@ err.emit(); } -pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(LocalDefId, EntryFnType)> { +pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> { tcx.entry_fn(LOCAL_CRATE) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/hir_id_validator.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/hir_id_validator.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/hir_id_validator.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/hir_id_validator.rs 2021-06-17 03:53:50.000000000 +0000 @@ -172,17 +172,4 @@ // we are currently in. So for those it's correct that they have a // different owner. } - - fn visit_generic_param(&mut self, param: &'hir hir::GenericParam<'hir>) { - if let hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } = param.kind - { - // Synthetic impl trait parameters are owned by the node of the desugared type. - // This means it is correct for them to have a different owner. - } else { - intravisit::walk_generic_param(self, param); - } - } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/intrinsicck.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/intrinsicck.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/intrinsicck.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/intrinsicck.rs 2021-06-17 03:53:50.000000000 +0000 @@ -347,7 +347,7 @@ } fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, (op, _op_sp)) in asm.operands.iter().enumerate() { + for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { self.check_asm_operand_type(idx, reg, expr, asm.template, None); @@ -372,14 +372,15 @@ ); } } - hir::InlineAsmOperand::Const { ref expr } => { - let ty = self.typeck_results.expr_ty_adjusted(expr); - match ty.kind() { + hir::InlineAsmOperand::Const { ref anon_const } => { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + match value.ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) => {} _ => { let msg = "asm `const` arguments must be integer or floating-point values"; - self.tcx.sess.span_err(expr.span, msg); + self.tcx.sess.span_err(*op_sp, msg); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -5,12 +5,12 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(const_fn)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/liveness/rwu_table.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/liveness/rwu_table.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/liveness/rwu_table.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/liveness/rwu_table.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,5 @@ use crate::liveness::{LiveNode, Variable}; +use std::iter; #[derive(Clone, Copy)] pub(super) struct RWU { @@ -91,7 +92,7 @@ let mut changed = false; let (dst_row, src_row) = self.pick2_rows_mut(dst, src); - for (dst_word, src_word) in dst_row.iter_mut().zip(src_row.iter()) { + for (dst_word, src_word) in iter::zip(dst_row, &*src_row) { let old = *dst_word; let new = *dst_word | src_word; *dst_word = new; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/liveness.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/liveness.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/liveness.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/liveness.rs 2021-06-17 03:53:50.000000000 +0000 @@ -103,6 +103,7 @@ use std::collections::VecDeque; use std::io; use std::io::prelude::*; +use std::iter; use std::rc::Rc; mod rwu_table; @@ -1066,7 +1067,6 @@ for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } - | hir::InlineAsmOperand::Const { expr, .. } | hir::InlineAsmOperand::Sym { expr, .. } => { succ = self.propagate_through_expr(expr, succ) } @@ -1084,6 +1084,7 @@ } succ = self.propagate_through_expr(in_expr, succ); } + hir::InlineAsmOperand::Const { .. } => {} } } succ @@ -1093,7 +1094,7 @@ let ia = &asm.inner; let outputs = asm.outputs_exprs; let inputs = asm.inputs_exprs; - let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| { + let succ = iter::zip(&ia.outputs, outputs).rev().fold(succ, |succ, (o, output)| { // see comment on places // in propagate_through_place_components() if o.is_indirect { @@ -1344,7 +1345,7 @@ } // Output operands must be places - for (o, output) in asm.inner.outputs.iter().zip(asm.outputs_exprs) { + for (o, output) in iter::zip(&asm.inner.outputs, asm.outputs_exprs) { if !o.is_indirect { this.check_place(output); } @@ -1475,7 +1476,7 @@ for p in body.params { self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| { if !self.live_on_entry(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value passed to `{}` is never read", name) }); } @@ -1614,13 +1615,13 @@ fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { if !self.live_on_exit(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value assigned to `{}` is never read", name) }); } } - fn report_unsed_assign( + fn report_unused_assign( &self, hir_id: HirId, spans: Vec, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/region.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/region.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/region.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/region.rs 2021-06-17 03:53:50.000000000 +0000 @@ -23,14 +23,6 @@ #[derive(Debug, Copy, Clone)] pub struct Context { - /// The root of the current region tree. This is typically the id - /// of the innermost fn body. Each fn forms its own disjoint tree - /// in the region hierarchy. These fn bodies are themselves - /// arranged into a tree. See the "Modeling closures" section of - /// the README in `rustc_trait_selection::infer::region_constraints` - /// for more details. - root_id: Option, - /// The scope that contains any new variables declared, plus its depth in /// the scope tree. var_parent: Option<(Scope, ScopeDepth)>, @@ -743,11 +735,6 @@ let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); self.terminating_scopes.insert(body.value.hir_id.local_id); - if let Some(root_id) = self.cx.root_id { - self.scope_tree.record_closure_parent(body.value.hir_id.local_id, root_id); - } - self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); @@ -824,7 +811,7 @@ tcx, scope_tree: ScopeTree::default(), expr_and_pat_count: 0, - cx: Context { root_id: None, parent: None, var_parent: None }, + cx: Context { parent: None, var_parent: None }, terminating_scopes: Default::default(), pessimistic_yield: false, fixup_scopes: vec![], diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/stability.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/stability.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_passes/src/stability.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_passes/src/stability.rs 2021-06-17 03:53:50.000000000 +0000 @@ -22,6 +22,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::cmp::Ordering; +use std::iter; use std::mem::replace; use std::num::NonZeroU32; @@ -214,7 +215,7 @@ { // Explicit version of iter::order::lt to handle parse errors properly for (dep_v, stab_v) in - dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) + iter::zip(dep_since.as_str().split('.'), stab_since.as_str().split('.')) { match stab_v.parse::() { Err(_) => { @@ -507,10 +508,9 @@ fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { let kind = match &p.kind { - // FIXME(const_generics_defaults) - hir::GenericParamKind::Type { default, .. } if default.is_some() => { - AnnotationKind::Container - } + // Allow stability attributes on default generic arguments. + hir::GenericParamKind::Type { default: Some(_), .. } + | hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container, _ => AnnotationKind::Prohibited, }; @@ -686,7 +686,7 @@ annotator.annotate( hir::CRATE_HIR_ID, - krate.item.span, + krate.item.inner, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -885,7 +885,7 @@ if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span); + missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.inner); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_privacy/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_privacy/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_privacy/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_privacy/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(control_flow_enum)] #![feature(try_blocks)] #![feature(associated_type_defaults)] @@ -928,8 +928,11 @@ self.visit(self.ev.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id)); + if has_default { + self.visit(self.ev.tcx.const_param_default(param.def_id)); + } } } } @@ -1111,7 +1114,7 @@ //////////////////////////////////////////////////////////////////////////////////////////// /// Type privacy visitor, checks types for privacy and reports violations. -/// Both explicitly written types and inferred types of expressions and patters are checked. +/// Both explicitly written types and inferred types of expressions and patterns are checked. /// Checks are performed on "semantic" types regardless of names and their hygiene. //////////////////////////////////////////////////////////////////////////////////////////// @@ -1741,7 +1744,8 @@ self.visit(self.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + // FIXME(const_evaluatable_checked): May want to look inside const here + GenericParamDefKind::Const { .. } => { self.visit(self.tcx.type_of(param.def_id)); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/keys.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/keys.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/keys.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/keys.rs 2021-06-17 03:53:50.000000000 +0000 @@ -255,6 +255,15 @@ } } +impl<'tcx> Key for mir::ConstantKind<'tcx> { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for &'tcx ty::Const<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -19,8 +19,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, Handler}; -use rustc_hir::def_id::CrateNum; -use rustc_index::vec::IndexVec; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph; use rustc_middle::ich::StableHashingContext; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/plumbing.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/plumbing.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/plumbing.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/plumbing.rs 2021-06-17 03:53:50.000000000 +0000 @@ -390,13 +390,12 @@ #[inline] fn compute(tcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - let provider = tcx.queries.providers.get(key.query_crate()) - // HACK(eddyb) it's possible crates may be loaded after - // the query engine is created, and because crate loading - // is not yet integrated with the query engine, such crates - // would be missing appropriate entries in `providers`. - .unwrap_or(&tcx.queries.fallback_extern_providers) - .$name; + let is_local = key.query_crate() == LOCAL_CRATE; + let provider = if is_local { + tcx.queries.local_providers.$name + } else { + tcx.queries.extern_providers.$name + }; provider(*tcx, key) } @@ -439,6 +438,11 @@ try_load_from_on_disk_cache: |_, _| {}, }; + pub const CompileMonoItem: QueryStruct = QueryStruct { + force_from_dep_node: |_, _| false, + try_load_from_on_disk_cache: |_, _| {}, + }; + $(pub const $name: QueryStruct = { const is_anon: bool = is_anon!([$($modifiers)*]); @@ -478,10 +482,7 @@ return } - debug_assert!(tcx.dep_graph - .node_color(dep_node) - .map(|c| c.is_green()) - .unwrap_or(false)); + debug_assert!(tcx.dep_graph.is_green(dep_node)); let key = recover(*tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)); if queries::$name::cache_on_disk(tcx, &key, None) { @@ -507,8 +508,8 @@ (tcx: $tcx:tt, input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { pub struct Queries<$tcx> { - providers: IndexVec, - fallback_extern_providers: Box, + local_providers: Box, + extern_providers: Box, $($(#[$attr])* $name: QueryState< crate::dep_graph::DepKind, @@ -518,12 +519,12 @@ impl<$tcx> Queries<$tcx> { pub fn new( - providers: IndexVec, - fallback_extern_providers: Providers, + local_providers: Providers, + extern_providers: Providers, ) -> Self { Queries { - providers, - fallback_extern_providers: Box::new(fallback_extern_providers), + local_providers: Box::new(local_providers), + extern_providers: Box::new(extern_providers), $($name: Default::default()),* } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/profiling_support.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/profiling_support.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/profiling_support.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/profiling_support.rs 2021-06-17 03:53:50.000000000 +0000 @@ -250,8 +250,8 @@ // need to invoke queries itself, we cannot keep the query caches // locked while doing so. Instead we copy out the // `(query_key, dep_node_index)` pairs and release the lock again. - let query_keys_and_indices: Vec<_> = query_cache - .iter_results(|results| results.map(|(k, _, i)| (k.clone(), i)).collect()); + let mut query_keys_and_indices = Vec::new(); + query_cache.iter_results(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i))); // Now actually allocate the strings. If allocating the strings // generates new entries in the query cache, we'll miss them but @@ -275,14 +275,15 @@ let query_name = profiler.get_or_alloc_cached_string(query_name); let event_id = event_id_builder.from_label(query_name).to_string_id(); - query_cache.iter_results(|results| { - let query_invocation_ids: Vec<_> = results.map(|v| v.2.into()).collect(); - - profiler.bulk_map_query_invocation_id_to_single_string( - query_invocation_ids.into_iter(), - event_id, - ); + let mut query_invocation_ids = Vec::new(); + query_cache.iter_results(&mut |_, _, i| { + query_invocation_ids.push(i.into()); }); + + profiler.bulk_map_query_invocation_id_to_single_string( + query_invocation_ids.into_iter(), + event_id, + ); } }); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/stats.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/stats.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_impl/src/stats.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_impl/src/stats.rs 2021-06-17 03:53:50.000000000 +0000 @@ -50,13 +50,12 @@ key_type: type_name::(), value_size: mem::size_of::(), value_type: type_name::(), - entry_count: map.iter_results(|results| results.count()), + entry_count: 0, local_def_id_keys: None, }; - map.iter_results(|results| { - for (key, _, _) in results { - key.key_stats(&mut stats) - } + map.iter_results(&mut |key, _, _| { + stats.entry_count += 1; + key.key_stats(&mut stats) }); stats } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/cache.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/cache.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/cache.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/cache.rs 2021-06-17 03:53:50.000000000 +0000 @@ -3,7 +3,6 @@ use crate::dep_graph::{DepContext, DepNodeIndex}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::HashMapExt; use rustc_data_structures::sync::Lock; use std::hash::Hash; @@ -34,13 +33,6 @@ pub fn insert(&self, key: Key, dep_node: DepNodeIndex, value: Value) { self.hashmap.borrow_mut().insert(key, WithDepNode::new(dep_node, value)); } - - pub fn insert_same(&self, key: Key, dep_node: DepNodeIndex, value: Value) - where - Value: Eq, - { - self.hashmap.borrow_mut().insert_same(key, WithDepNode::new(dep_node, value)); - } } #[derive(Clone, Eq, PartialEq)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/debug.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/debug.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/debug.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/debug.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,8 @@ //! Code for debugging the dep-graph. -use super::{DepKind, DepNode}; +use super::{DepKind, DepNode, DepNodeIndex}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lock; use std::error::Error; /// A dep-node filter goes from a user-defined string to a query over @@ -34,13 +36,14 @@ /// A filter like `F -> G` where `F` and `G` are valid dep-node /// filters. This can be used to test the source/target independently. -pub struct EdgeFilter { +pub struct EdgeFilter { pub source: DepNodeFilter, pub target: DepNodeFilter, + pub index_to_node: Lock>>, } -impl EdgeFilter { - pub fn new(test: &str) -> Result> { +impl EdgeFilter { + pub fn new(test: &str) -> Result, Box> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into()) @@ -48,11 +51,13 @@ Ok(EdgeFilter { source: DepNodeFilter::new(parts[0]), target: DepNodeFilter::new(parts[1]), + index_to_node: Lock::new(FxHashMap::default()), }) } } - pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { + #[cfg(debug_assertions)] + pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { self.source.test(source) && self.target.test(target) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/dep_node.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/dep_node.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/dep_node.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/dep_node.rs 2021-06-17 03:53:50.000000000 +0000 @@ -26,7 +26,7 @@ //! could not be instantiated because the current compilation session //! contained no `DefId` for thing that had been removed. //! -//! `DepNode` definition happens in `librustc_middle` with the `define_dep_nodes!()` macro. +//! `DepNode` definition happens in `rustc_middle` with the `define_dep_nodes!()` macro. //! This macro defines the `DepKind` enum and a corresponding `DepConstructor` enum. The //! `DepConstructor` enum links a `DepKind` to the parameters that are needed at runtime in order //! to construct a valid `DepNode` fingerprint. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/graph.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/graph.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/graph.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/graph.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,31 +1,33 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::QueryInvocationId; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, LockGuard, Lrc, Ordering}; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; use rustc_data_structures::unlikely; use rustc_errors::Diagnostic; -use rustc_index::vec::{Idx, IndexVec}; -use rustc_serialize::{Encodable, Encoder}; +use rustc_index::vec::IndexVec; +use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use parking_lot::{Condvar, Mutex}; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; -use std::env; use std::hash::Hash; use std::marker::PhantomData; use std::mem; -use std::ops::Range; use std::sync::atomic::Ordering::Relaxed; -use super::debug::EdgeFilter; use super::prev::PreviousDepGraph; use super::query::DepGraphQuery; -use super::serialized::SerializedDepNodeIndex; +use super::serialized::{GraphEncoder, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; use crate::query::QueryContext; +#[cfg(debug_assertions)] +use {super::debug::EdgeFilter, std::env}; + #[derive(Clone)] pub struct DepGraph { data: Option>>, @@ -109,6 +111,9 @@ pub fn new( prev_graph: PreviousDepGraph, prev_work_products: FxHashMap, + encoder: FileEncoder, + record_graph: bool, + record_stats: bool, ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); @@ -116,7 +121,12 @@ data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: CurrentDepGraph::new(prev_graph_node_count), + current: CurrentDepGraph::new( + prev_graph_node_count, + encoder, + record_graph, + record_stats, + ), emitting_diagnostics: Default::default(), emitting_diagnostics_cond_var: Condvar::new(), previous: prev_graph, @@ -136,62 +146,10 @@ self.data.is_some() } - pub fn query(&self) -> DepGraphQuery { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - - // Note locking order: `prev_index_to_index`, then `data`. - let prev_index_to_index = data.current.prev_index_to_index.lock(); - let data = data.current.data.lock(); - let node_count = data.hybrid_indices.len(); - let edge_count = self.edge_count(&data); - - let mut nodes = Vec::with_capacity(node_count); - let mut edge_list_indices = Vec::with_capacity(node_count); - let mut edge_list_data = Vec::with_capacity(edge_count); - - // See `DepGraph`'s `Encodable` implementation for notes on the approach used here. - - edge_list_data.extend(data.unshared_edges.iter().map(|i| i.index())); - - for &hybrid_index in data.hybrid_indices.iter() { - match hybrid_index.into() { - HybridIndex::New(new_index) => { - nodes.push(data.new.nodes[new_index]); - let edges = &data.new.edges[new_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::Red(red_index) => { - nodes.push(previous.index_to_node(data.red.node_indices[red_index])); - let edges = &data.red.edges[red_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::LightGreen(lg_index) => { - nodes.push(previous.index_to_node(data.light_green.node_indices[lg_index])); - let edges = &data.light_green.edges[lg_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::DarkGreen(prev_index) => { - nodes.push(previous.index_to_node(prev_index)); - - let edges_iter = previous - .edge_targets_from(prev_index) - .iter() - .map(|&dst| prev_index_to_index[dst].unwrap().index()); - - let start = edge_list_data.len(); - edge_list_data.extend(edges_iter); - let end = edge_list_data.len(); - edge_list_indices.push((start, end)); - } - } + pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + if let Some(data) = &self.data { + data.current.encoder.borrow().with_query(f) } - - debug_assert_eq!(nodes.len(), node_count); - debug_assert_eq!(edge_list_indices.len(), node_count); - debug_assert_eq!(edge_list_data.len(), edge_count); - - DepGraphQuery::new(&nodes[..], &edge_list_indices[..], &edge_list_data[..]) } pub fn assert_ignored(&self) { @@ -283,56 +241,16 @@ let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; // Intern the new `DepNode`. - let dep_node_index = if let Some(prev_index) = data.previous.node_to_index_opt(&key) { - // Determine the color and index of the new `DepNode`. - let (color, dep_node_index) = if let Some(current_fingerprint) = current_fingerprint - { - if current_fingerprint == data.previous.fingerprint_by_index(prev_index) { - if print_status { - eprintln!("[task::green] {:?}", key); - } - - // This is a light green node: it existed in the previous compilation, - // its query was re-executed, and it has the same result as before. - let dep_node_index = - data.current.intern_light_green_node(&data.previous, prev_index, edges); - - (DepNodeColor::Green(dep_node_index), dep_node_index) - } else { - if print_status { - eprintln!("[task::red] {:?}", key); - } - - // This is a red node: it existed in the previous compilation, its query - // was re-executed, but it has a different result from before. - let dep_node_index = data.current.intern_red_node( - &data.previous, - prev_index, - edges, - current_fingerprint, - ); - - (DepNodeColor::Red, dep_node_index) - } - } else { - if print_status { - eprintln!("[task::unknown] {:?}", key); - } - - // This is a red node, effectively: it existed in the previous compilation - // session, its query was re-executed, but it doesn't compute a result hash - // (i.e. it represents a `no_hash` query), so we have no way of determining - // whether or not the result was the same as before. - let dep_node_index = data.current.intern_red_node( - &data.previous, - prev_index, - edges, - Fingerprint::ZERO, - ); - - (DepNodeColor::Red, dep_node_index) - }; + let (dep_node_index, prev_and_color) = data.current.intern_node( + dcx.profiler(), + &data.previous, + key, + edges, + current_fingerprint, + print_status, + ); + if let Some((prev_index, color)) = prev_and_color { debug_assert!( data.colors.get(prev_index).is_none(), "DepGraph::with_task() - Duplicate DepNodeColor \ @@ -341,20 +259,7 @@ ); data.colors.insert(prev_index, color); - dep_node_index - } else { - if print_status { - eprintln!("[task::new] {:?}", key); - } - - // This is a new node: it didn't exist in the previous compilation session. - data.current.intern_new_node( - &data.previous, - key, - edges, - current_fingerprint.unwrap_or(Fingerprint::ZERO), - ) - }; + } (result, dep_node_index) } else { @@ -368,7 +273,12 @@ /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task(&self, dep_kind: K, op: OP) -> (R, DepNodeIndex) + pub fn with_anon_task, OP, R>( + &self, + cx: Ctxt, + dep_kind: K, + op: OP, + ) -> (R, DepNodeIndex) where OP: FnOnce() -> R, { @@ -396,7 +306,7 @@ }; let dep_node_index = data.current.intern_new_node( - &data.previous, + cx.profiler(), target_dep_node, task_deps.reads, Fingerprint::ZERO, @@ -451,7 +361,7 @@ { if let Some(target) = task_deps.node { if let Some(ref forbidden_edge) = data.current.forbidden_edge { - let src = self.dep_node_of(dep_node_index); + let src = forbidden_edge.index_to_node.lock()[&dep_node_index]; if forbidden_edge.test(&src, &target) { panic!("forbidden edge {:?} -> {:?} created", src, target) } @@ -488,38 +398,6 @@ self.data.is_some() && self.dep_node_index_of_opt(dep_node).is_some() } - #[inline] - pub fn dep_node_of(&self, dep_node_index: DepNodeIndex) -> DepNode { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - let data = data.current.data.lock(); - - match data.hybrid_indices[dep_node_index].into() { - HybridIndex::New(new_index) => data.new.nodes[new_index], - HybridIndex::Red(red_index) => previous.index_to_node(data.red.node_indices[red_index]), - HybridIndex::LightGreen(light_green_index) => { - previous.index_to_node(data.light_green.node_indices[light_green_index]) - } - HybridIndex::DarkGreen(prev_index) => previous.index_to_node(prev_index), - } - } - - #[inline] - pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - let data = data.current.data.lock(); - - match data.hybrid_indices[dep_node_index].into() { - HybridIndex::New(new_index) => data.new.fingerprints[new_index], - HybridIndex::Red(red_index) => data.red.fingerprints[red_index], - HybridIndex::LightGreen(light_green_index) => { - previous.fingerprint_by_index(data.light_green.node_indices[light_green_index]) - } - HybridIndex::DarkGreen(prev_index) => previous.fingerprint_by_index(prev_index), - } - } - pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { self.data.as_ref().unwrap().previous.fingerprint_of(dep_node) } @@ -554,29 +432,13 @@ self.data.as_ref()?.dep_node_debug.borrow().get(&dep_node).cloned() } - fn edge_count(&self, node_data: &LockGuard<'_, DepNodeData>) -> usize { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - - let mut edge_count = node_data.unshared_edges.len(); - - for &hybrid_index in node_data.hybrid_indices.iter() { - if let HybridIndex::DarkGreen(prev_index) = hybrid_index.into() { - edge_count += previous.edge_targets_from(prev_index).len() - } - } - - edge_count - } - - pub fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(ref data) = self.data { if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) { return data.colors.get(prev_index); } else { - // This is a node that did not exist in the previous compilation - // session, so we consider it to be red. - return Some(DepNodeColor::Red); + // This is a node that did not exist in the previous compilation session. + return None; } } @@ -775,11 +637,13 @@ // There may be multiple threads trying to mark the same dep node green concurrently - let dep_node_index = { - // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - data.current.intern_dark_green_node(&data.previous, prev_dep_node_index) - }; + // We allocating an entry for the node in the current dependency graph and + // adding all the appropriate edges imported from the previous graph + let dep_node_index = data.current.promote_node_and_deps_to_current( + tcx.dep_context().profiler(), + &data.previous, + prev_dep_node_index, + ); // ... emitting any stored diagnostic ... @@ -862,6 +726,12 @@ } } + // Returns true if the given node has been marked as red during the + // current compilation session. Used in various assertions + pub fn is_red(&self, dep_node: &DepNode) -> bool { + self.node_color(dep_node) == Some(DepNodeColor::Red) + } + // Returns true if the given node has been marked as green during the // current compilation session. Used in various assertions pub fn is_green(&self, dep_node: &DepNode) -> bool { @@ -911,106 +781,20 @@ } pub fn print_incremental_info(&self) { - #[derive(Clone)] - struct Stat { - kind: Kind, - node_counter: u64, - edge_counter: u64, + if let Some(data) = &self.data { + data.current.encoder.borrow().print_incremental_info( + data.current.total_read_count.load(Relaxed), + data.current.total_duplicate_read_count.load(Relaxed), + ) } + } - let data = self.data.as_ref().unwrap(); - let prev = &data.previous; - let current = &data.current; - let data = current.data.lock(); - - let mut stats: FxHashMap<_, Stat> = FxHashMap::with_hasher(Default::default()); - - for &hybrid_index in data.hybrid_indices.iter() { - let (kind, edge_count) = match hybrid_index.into() { - HybridIndex::New(new_index) => { - let kind = data.new.nodes[new_index].kind; - let edge_range = &data.new.edges[new_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::Red(red_index) => { - let kind = prev.index_to_node(data.red.node_indices[red_index]).kind; - let edge_range = &data.red.edges[red_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::LightGreen(lg_index) => { - let kind = prev.index_to_node(data.light_green.node_indices[lg_index]).kind; - let edge_range = &data.light_green.edges[lg_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::DarkGreen(prev_index) => { - let kind = prev.index_to_node(prev_index).kind; - let edge_count = prev.edge_targets_from(prev_index).len(); - (kind, edge_count) - } - }; - - let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); - stat.node_counter += 1; - stat.edge_counter += edge_count as u64; - } - - let total_node_count = data.hybrid_indices.len(); - let total_edge_count = self.edge_count(&data); - - // Drop the lock guard. - std::mem::drop(data); - - let mut stats: Vec<_> = stats.values().cloned().collect(); - stats.sort_by_key(|s| -(s.node_counter as i64)); - - const SEPARATOR: &str = "[incremental] --------------------------------\ - ----------------------------------------------\ - ------------"; - - eprintln!("[incremental]"); - eprintln!("[incremental] DepGraph Statistics"); - eprintln!("{}", SEPARATOR); - eprintln!("[incremental]"); - eprintln!("[incremental] Total Node Count: {}", total_node_count); - eprintln!("[incremental] Total Edge Count: {}", total_edge_count); - - if cfg!(debug_assertions) { - let total_edge_reads = current.total_read_count.load(Relaxed); - let total_duplicate_edge_reads = current.total_duplicate_read_count.load(Relaxed); - - eprintln!("[incremental] Total Edge Reads: {}", total_edge_reads); - eprintln!("[incremental] Total Duplicate Edge Reads: {}", total_duplicate_edge_reads); - } - - eprintln!("[incremental]"); - - eprintln!( - "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", - "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" - ); - - eprintln!( - "[incremental] -------------------------------------\ - |------------------\ - |-------------\ - |------------------|" - ); - - for stat in stats { - let node_kind_ratio = (100.0 * (stat.node_counter as f64)) / (total_node_count as f64); - let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); - - eprintln!( - "[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", - format!("{:?}", stat.kind), - node_kind_ratio, - stat.node_counter, - node_kind_avg_edges, - ); + pub fn encode(&self, profiler: &SelfProfilerRef) -> FileEncodeResult { + if let Some(data) = &self.data { + data.current.encoder.steal().finish(profiler) + } else { + Ok(()) } - - eprintln!("{}", SEPARATOR); - eprintln!("[incremental]"); } fn next_virtual_depnode_index(&self) -> DepNodeIndex { @@ -1019,142 +803,6 @@ } } -impl> Encodable for DepGraph { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - // We used to serialize the dep graph by creating and serializing a `SerializedDepGraph` - // using data copied from the `DepGraph`. But copying created a large memory spike, so we - // now serialize directly from the `DepGraph` as if it's a `SerializedDepGraph`. Because we - // deserialize that data into a `SerializedDepGraph` in the next compilation session, we - // need `DepGraph`'s `Encodable` and `SerializedDepGraph`'s `Decodable` implementations to - // be in sync. If you update this encoding, be sure to update the decoding, and vice-versa. - - let data = self.data.as_ref().unwrap(); - let prev = &data.previous; - - // Note locking order: `prev_index_to_index`, then `data`. - let prev_index_to_index = data.current.prev_index_to_index.lock(); - let data = data.current.data.lock(); - let new = &data.new; - let red = &data.red; - let lg = &data.light_green; - - let node_count = data.hybrid_indices.len(); - let edge_count = self.edge_count(&data); - - // `rustc_middle::ty::query::OnDiskCache` expects nodes to be encoded in `DepNodeIndex` - // order. The edges in `edge_list_data` don't need to be in a particular order, as long as - // each node references its edges as a contiguous range within it. Therefore, we can encode - // `edge_list_data` directly from `unshared_edges`. It meets the above requirements, as - // each non-dark-green node already knows the range of edges to reference within it, which - // they'll encode in `edge_list_indices`. Dark green nodes, however, don't have their edges - // in `unshared_edges`, so need to add them to `edge_list_data`. - - use HybridIndex::*; - - // Encoded values (nodes, etc.) are explicitly typed below to avoid inadvertently - // serializing data in the wrong format (i.e. one incompatible with `SerializedDepGraph`). - e.emit_struct("SerializedDepGraph", 4, |e| { - e.emit_struct_field("nodes", 0, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `DepNode`s. - e.emit_seq(node_count, |e| { - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let node: DepNode = match hybrid_index.into() { - New(i) => new.nodes[i], - Red(i) => prev.index_to_node(red.node_indices[i]), - LightGreen(i) => prev.index_to_node(lg.node_indices[i]), - DarkGreen(prev_index) => prev.index_to_node(prev_index), - }; - - e.emit_seq_elt(seq_index, |e| node.encode(e))?; - } - - Ok(()) - }) - })?; - - e.emit_struct_field("fingerprints", 1, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `Fingerprints`s. - e.emit_seq(node_count, |e| { - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let fingerprint: Fingerprint = match hybrid_index.into() { - New(i) => new.fingerprints[i], - Red(i) => red.fingerprints[i], - LightGreen(i) => prev.fingerprint_by_index(lg.node_indices[i]), - DarkGreen(prev_index) => prev.fingerprint_by_index(prev_index), - }; - - e.emit_seq_elt(seq_index, |e| fingerprint.encode(e))?; - } - - Ok(()) - }) - })?; - - e.emit_struct_field("edge_list_indices", 2, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `(u32, u32)`s. - e.emit_seq(node_count, |e| { - // Dark green node edges start after the unshared (all other nodes') edges. - let mut dark_green_edge_index = data.unshared_edges.len(); - - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let edge_indices: (u32, u32) = match hybrid_index.into() { - New(i) => (new.edges[i].start.as_u32(), new.edges[i].end.as_u32()), - Red(i) => (red.edges[i].start.as_u32(), red.edges[i].end.as_u32()), - LightGreen(i) => (lg.edges[i].start.as_u32(), lg.edges[i].end.as_u32()), - DarkGreen(prev_index) => { - let edge_count = prev.edge_targets_from(prev_index).len(); - let start = dark_green_edge_index as u32; - dark_green_edge_index += edge_count; - let end = dark_green_edge_index as u32; - (start, end) - } - }; - - e.emit_seq_elt(seq_index, |e| edge_indices.encode(e))?; - } - - assert_eq!(dark_green_edge_index, edge_count); - - Ok(()) - }) - })?; - - e.emit_struct_field("edge_list_data", 3, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of - // `SerializedDepNodeIndex`. - e.emit_seq(edge_count, |e| { - for (seq_index, &edge) in data.unshared_edges.iter().enumerate() { - let serialized_edge = SerializedDepNodeIndex::new(edge.index()); - e.emit_seq_elt(seq_index, |e| serialized_edge.encode(e))?; - } - - let mut seq_index = data.unshared_edges.len(); - - for &hybrid_index in data.hybrid_indices.iter() { - if let DarkGreen(prev_index) = hybrid_index.into() { - for &edge in prev.edge_targets_from(prev_index) { - // Dark green node edges are stored in the previous graph - // and must be converted to edges in the current graph, - // and then serialized as `SerializedDepNodeIndex`. - let serialized_edge = SerializedDepNodeIndex::new( - prev_index_to_index[edge].as_ref().unwrap().index(), - ); - - e.emit_seq_elt(seq_index, |e| serialized_edge.encode(e))?; - seq_index += 1; - } - } - } - - assert_eq!(seq_index, edge_count); - - Ok(()) - }) - }) - }) - } -} - /// A "work product" is an intermediate result that we save into the /// incremental directory for later re-use. The primary example are /// the object files that we save for each partition at code @@ -1193,216 +841,20 @@ pub saved_file: Option, } -// The maximum value of the follow index types leaves the upper two bits unused -// so that we can store multiple index types in `CompressedHybridIndex`, and use -// those bits to encode which index type it contains. - -// Index type for `NewDepNodeData`. -rustc_index::newtype_index! { - struct NewDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -// Index type for `RedDepNodeData`. -rustc_index::newtype_index! { - struct RedDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -// Index type for `LightGreenDepNodeData`. -rustc_index::newtype_index! { - struct LightGreenDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -/// Compressed representation of `HybridIndex` enum. Bits unused by the -/// contained index types are used to encode which index type it contains. -#[derive(Copy, Clone)] -struct CompressedHybridIndex(u32); - -impl CompressedHybridIndex { - const NEW_TAG: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0000; - const RED_TAG: u32 = 0b0100_0000_0000_0000_0000_0000_0000_0000; - const LIGHT_GREEN_TAG: u32 = 0b1000_0000_0000_0000_0000_0000_0000_0000; - const DARK_GREEN_TAG: u32 = 0b1100_0000_0000_0000_0000_0000_0000_0000; - - const TAG_MASK: u32 = 0b1100_0000_0000_0000_0000_0000_0000_0000; - const INDEX_MASK: u32 = !Self::TAG_MASK; -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: NewDepNodeIndex) -> Self { - CompressedHybridIndex(Self::NEW_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: RedDepNodeIndex) -> Self { - CompressedHybridIndex(Self::RED_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: LightGreenDepNodeIndex) -> Self { - CompressedHybridIndex(Self::LIGHT_GREEN_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: SerializedDepNodeIndex) -> Self { - CompressedHybridIndex(Self::DARK_GREEN_TAG | index.as_u32()) - } -} - -/// Contains an index into one of several node data collections. Elsewhere, we -/// store `CompressedHyridIndex` instead of this to save space, but convert to -/// this type during processing to take advantage of the enum match ergonomics. -enum HybridIndex { - New(NewDepNodeIndex), - Red(RedDepNodeIndex), - LightGreen(LightGreenDepNodeIndex), - DarkGreen(SerializedDepNodeIndex), -} - -impl From for HybridIndex { - #[inline] - fn from(hybrid_index: CompressedHybridIndex) -> Self { - let index = hybrid_index.0 & CompressedHybridIndex::INDEX_MASK; - - match hybrid_index.0 & CompressedHybridIndex::TAG_MASK { - CompressedHybridIndex::NEW_TAG => HybridIndex::New(NewDepNodeIndex::from_u32(index)), - CompressedHybridIndex::RED_TAG => HybridIndex::Red(RedDepNodeIndex::from_u32(index)), - CompressedHybridIndex::LIGHT_GREEN_TAG => { - HybridIndex::LightGreen(LightGreenDepNodeIndex::from_u32(index)) - } - CompressedHybridIndex::DARK_GREEN_TAG => { - HybridIndex::DarkGreen(SerializedDepNodeIndex::from_u32(index)) - } - _ => unreachable!(), - } - } -} - // Index type for `DepNodeData`'s edges. rustc_index::newtype_index! { struct EdgeIndex { .. } } -/// Data for nodes in the current graph, divided into different collections -/// based on their presence in the previous graph, and if present, their color. -/// We divide nodes this way because different types of nodes are able to share -/// more or less data with the previous graph. -/// -/// To enable more sharing, we distinguish between two kinds of green nodes. -/// Light green nodes are nodes in the previous graph that have been marked -/// green because we re-executed their queries and the results were the same as -/// in the previous session. Dark green nodes are nodes in the previous graph -/// that have been marked green because we were able to mark all of their -/// dependencies green. -/// -/// Both light and dark green nodes can share the dep node and fingerprint with -/// the previous graph, but for light green nodes, we can't be sure that the -/// edges may be shared without comparing them against the previous edges, so we -/// store them directly (an approach in which we compare edges with the previous -/// edges to see if they can be shared was evaluated, but was not found to be -/// very profitable). -/// -/// For dark green nodes, we can share everything with the previous graph, which -/// is why the `HybridIndex::DarkGreen` enum variant contains the index of the -/// node in the previous graph, and why we don't have a separate collection for -/// dark green node data--the collection is the `PreviousDepGraph` itself. -/// -/// (Note that for dark green nodes, the edges in the previous graph -/// (`SerializedDepNodeIndex`s) must be converted to edges in the current graph -/// (`DepNodeIndex`s). `CurrentDepGraph` contains `prev_index_to_index`, which -/// can perform this conversion. It should always be possible, as by definition, -/// a dark green node is one whose dependencies from the previous session have -/// all been marked green--which means `prev_index_to_index` contains them.) -/// -/// Node data is stored in parallel vectors to eliminate the padding between -/// elements that would be needed to satisfy alignment requirements of the -/// structure that would contain all of a node's data. We could group tightly -/// packing subsets of node data together and use fewer vectors, but for -/// consistency's sake, we use separate vectors for each piece of data. -struct DepNodeData { - /// Data for nodes not in previous graph. - new: NewDepNodeData, - - /// Data for nodes in previous graph that have been marked red. - red: RedDepNodeData, - - /// Data for nodes in previous graph that have been marked light green. - light_green: LightGreenDepNodeData, - - // Edges for all nodes other than dark-green ones. Edges for each node - // occupy a contiguous region of this collection, which a node can reference - // using two indices. Storing edges this way rather than using an `EdgesVec` - // for each node reduces memory consumption by a not insignificant amount - // when compiling large crates. The downside is that we have to copy into - // this collection the edges from the `EdgesVec`s that are built up during - // query execution. But this is mostly balanced out by the more efficient - // implementation of `DepGraph::serialize` enabled by this representation. - unshared_edges: IndexVec, - - /// Mapping from `DepNodeIndex` to an index into a collection above. - /// Indicates which of the above collections contains a node's data. - /// - /// This collection is wasteful in time and space during incr-full builds, - /// because for those, all nodes are new. However, the waste is relatively - /// small, and the maintenance cost of avoiding using this for incr-full - /// builds is somewhat high and prone to bugginess. It does not seem worth - /// it at the time of this writing, but we may want to revisit the idea. - hybrid_indices: IndexVec, -} - -/// Data for nodes not in previous graph. Since we cannot share any data with -/// the previous graph, so we must store all of such a node's data here. -struct NewDepNodeData { - nodes: IndexVec>, - edges: IndexVec>, - fingerprints: IndexVec, -} - -/// Data for nodes in previous graph that have been marked red. We can share the -/// dep node with the previous graph, but the edges may be different, and the -/// fingerprint is known to be different, so we store the latter two directly. -struct RedDepNodeData { - node_indices: IndexVec, - edges: IndexVec>, - fingerprints: IndexVec, -} - -/// Data for nodes in previous graph that have been marked green because we -/// re-executed their queries and the results were the same as in the previous -/// session. We can share the dep node and the fingerprint with the previous -/// graph, but the edges may be different, so we store them directly. -struct LightGreenDepNodeData { - node_indices: IndexVec, - edges: IndexVec>, -} - /// `CurrentDepGraph` stores the dependency graph for the current session. It /// will be populated as we run queries or tasks. We never remove nodes from the /// graph: they are only added. /// -/// The nodes in it are identified by a `DepNodeIndex`. Internally, this maps to -/// a `HybridIndex`, which identifies which collection in the `data` field -/// contains a node's data. Which collection is used for a node depends on -/// whether the node was present in the `PreviousDepGraph`, and if so, the color -/// of the node. Each type of node can share more or less data with the previous -/// graph. When possible, we can store just the index of the node in the -/// previous graph, rather than duplicating its data in our own collections. -/// This is important, because these graph structures are some of the largest in -/// the compiler. +/// The nodes in it are identified by a `DepNodeIndex`. We avoid keeping the nodes +/// in memory. This is important, because these graph structures are some of the +/// largest in the compiler. /// -/// For the same reason, we also avoid storing `DepNode`s more than once as map +/// For this reason, we avoid storing `DepNode`s more than once as map /// keys. The `new_node_to_index` map only contains nodes not in the previous /// graph, and we map nodes in the previous graph to indices via a two-step /// mapping. `PreviousDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`, @@ -1417,15 +869,15 @@ /// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When /// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index` /// first, and `data` second. -pub(super) struct CurrentDepGraph { - data: Lock>, +pub(super) struct CurrentDepGraph { + encoder: Steal>, new_node_to_index: Sharded, DepNodeIndex>>, prev_index_to_index: Lock>>, /// Used to trap when a specific edge is added to the graph. /// This is used for debug purposes and is only active with `debug_assertions`. - #[allow(dead_code)] - forbidden_edge: Option, + #[cfg(debug_assertions)] + forbidden_edge: Option>, /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of /// their edges. This has the beneficial side-effect that multiple anonymous @@ -1447,7 +899,12 @@ } impl CurrentDepGraph { - fn new(prev_graph_node_count: usize) -> CurrentDepGraph { + fn new( + prev_graph_node_count: usize, + encoder: FileEncoder, + record_graph: bool, + record_stats: bool, + ) -> CurrentDepGraph { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -1455,70 +912,29 @@ let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); - let forbidden_edge = if cfg!(debug_assertions) { - match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { - Ok(s) => match EdgeFilter::new(&s) { - Ok(f) => Some(f), - Err(err) => panic!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), - }, - Err(_) => None, - } - } else { - None + #[cfg(debug_assertions)] + let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { + Ok(s) => match EdgeFilter::new(&s) { + Ok(f) => Some(f), + Err(err) => panic!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + }, + Err(_) => None, }; - // Pre-allocate the dep node structures. We over-allocate a little so - // that we hopefully don't have to re-allocate during this compilation - // session. The over-allocation for new nodes is 2% plus a small - // constant to account for the fact that in very small crates 2% might - // not be enough. The allocation for red and green node data doesn't - // include a constant, as we don't want to allocate anything for these - // structures during full incremental builds, where they aren't used. - // - // These estimates are based on the distribution of node and edge counts - // seen in rustc-perf benchmarks, adjusted somewhat to account for the - // fact that these benchmarks aren't perfectly representative. - // - // FIXME Use a collection type that doesn't copy node and edge data and - // grow multiplicatively on reallocation. Without such a collection or - // solution having the same effect, there is a performance hazard here - // in both time and space, as growing these collections means copying a - // large amount of data and doubling already large buffer capacities. A - // solution for this will also mean that it's less important to get - // these estimates right. - let new_node_count_estimate = (prev_graph_node_count * 2) / 100 + 200; - let red_node_count_estimate = (prev_graph_node_count * 3) / 100; - let light_green_node_count_estimate = (prev_graph_node_count * 25) / 100; - let total_node_count_estimate = prev_graph_node_count + new_node_count_estimate; - - let average_edges_per_node_estimate = 6; - let unshared_edge_count_estimate = average_edges_per_node_estimate - * (new_node_count_estimate + red_node_count_estimate + light_green_node_count_estimate); - // We store a large collection of these in `prev_index_to_index` during // non-full incremental builds, and want to ensure that the element size // doesn't inadvertently increase. static_assert_size!(Option, 4); + let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200; + CurrentDepGraph { - data: Lock::new(DepNodeData { - new: NewDepNodeData { - nodes: IndexVec::with_capacity(new_node_count_estimate), - edges: IndexVec::with_capacity(new_node_count_estimate), - fingerprints: IndexVec::with_capacity(new_node_count_estimate), - }, - red: RedDepNodeData { - node_indices: IndexVec::with_capacity(red_node_count_estimate), - edges: IndexVec::with_capacity(red_node_count_estimate), - fingerprints: IndexVec::with_capacity(red_node_count_estimate), - }, - light_green: LightGreenDepNodeData { - node_indices: IndexVec::with_capacity(light_green_node_count_estimate), - edges: IndexVec::with_capacity(light_green_node_count_estimate), - }, - unshared_edges: IndexVec::with_capacity(unshared_edge_count_estimate), - hybrid_indices: IndexVec::with_capacity(total_node_count_estimate), - }), + encoder: Steal::new(GraphEncoder::new( + encoder, + prev_graph_node_count, + record_graph, + record_stats, + )), new_node_to_index: Sharded::new(|| { FxHashMap::with_capacity_and_hasher( new_node_count_estimate / sharded::SHARDS, @@ -1527,89 +943,143 @@ }), prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), anon_id_seed: stable_hasher.finish(), + #[cfg(debug_assertions)] forbidden_edge, total_read_count: AtomicU64::new(0), total_duplicate_read_count: AtomicU64::new(0), } } + #[cfg(debug_assertions)] + fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode) { + if let Some(forbidden_edge) = &self.forbidden_edge { + forbidden_edge.index_to_node.lock().insert(dep_node_index, key); + } + } + + /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. + /// Assumes that this is a node that has no equivalent in the previous dep-graph. fn intern_new_node( &self, - prev_graph: &PreviousDepGraph, - dep_node: DepNode, + profiler: &SelfProfilerRef, + key: DepNode, edges: EdgesVec, - fingerprint: Fingerprint, + current_fingerprint: Fingerprint, ) -> DepNodeIndex { - debug_assert!( - prev_graph.node_to_index_opt(&dep_node).is_none(), - "node in previous graph should be interned using one \ - of `intern_red_node`, `intern_light_green_node`, etc." - ); - - match self.new_node_to_index.get_shard_by_value(&dep_node).lock().entry(dep_node) { + match self.new_node_to_index.get_shard_by_value(&key).lock().entry(key) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { - let data = &mut *self.data.lock(); - let new_index = data.new.nodes.push(dep_node); - add_edges(&mut data.unshared_edges, &mut data.new.edges, edges); - data.new.fingerprints.push(fingerprint); - let dep_node_index = data.hybrid_indices.push(new_index.into()); + let dep_node_index = + self.encoder.borrow().send(profiler, key, current_fingerprint, edges); entry.insert(dep_node_index); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); dep_node_index } } } - fn intern_red_node( + fn intern_node( &self, + profiler: &SelfProfilerRef, prev_graph: &PreviousDepGraph, - prev_index: SerializedDepNodeIndex, + key: DepNode, edges: EdgesVec, - fingerprint: Fingerprint, - ) -> DepNodeIndex { - self.debug_assert_not_in_new_nodes(prev_graph, prev_index); + fingerprint: Option, + print_status: bool, + ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) { + let print_status = cfg!(debug_assertions) && print_status; + + if let Some(prev_index) = prev_graph.node_to_index_opt(&key) { + // Determine the color and index of the new `DepNode`. + if let Some(fingerprint) = fingerprint { + if fingerprint == prev_graph.fingerprint_by_index(prev_index) { + if print_status { + eprintln!("[task::green] {:?}", key); + } - let mut prev_index_to_index = self.prev_index_to_index.lock(); + // This is a green node: it existed in the previous compilation, + // its query was re-executed, and it has the same result as before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, fingerprint, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; - match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let data = &mut *self.data.lock(); - let red_index = data.red.node_indices.push(prev_index); - add_edges(&mut data.unshared_edges, &mut data.red.edges, edges); - data.red.fingerprints.push(fingerprint); - let dep_node_index = data.hybrid_indices.push(red_index.into()); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - } - } + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index)))) + } else { + if print_status { + eprintln!("[task::red] {:?}", key); + } - fn intern_light_green_node( - &self, - prev_graph: &PreviousDepGraph, - prev_index: SerializedDepNodeIndex, - edges: EdgesVec, - ) -> DepNodeIndex { - self.debug_assert_not_in_new_nodes(prev_graph, prev_index); + // This is a red node: it existed in the previous compilation, its query + // was re-executed, but it has a different result from before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, fingerprint, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; - let mut prev_index_to_index = self.prev_index_to_index.lock(); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Red))) + } + } else { + if print_status { + eprintln!("[task::unknown] {:?}", key); + } - match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let data = &mut *self.data.lock(); - let light_green_index = data.light_green.node_indices.push(prev_index); - add_edges(&mut data.unshared_edges, &mut data.light_green.edges, edges); - let dep_node_index = data.hybrid_indices.push(light_green_index.into()); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index + // This is a red node, effectively: it existed in the previous compilation + // session, its query was re-executed, but it doesn't compute a result hash + // (i.e. it represents a `no_hash` query), so we have no way of determining + // whether or not the result was the same as before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, Fingerprint::ZERO, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; + + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Red))) + } + } else { + if print_status { + eprintln!("[task::new] {:?}", key); } + + let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); + + // This is a new node: it didn't exist in the previous compilation session. + let dep_node_index = self.intern_new_node(profiler, key, edges, fingerprint); + + (dep_node_index, None) } } - fn intern_dark_green_node( + fn promote_node_and_deps_to_current( &self, + profiler: &SelfProfilerRef, prev_graph: &PreviousDepGraph, prev_index: SerializedDepNodeIndex, ) -> DepNodeIndex { @@ -1620,9 +1090,20 @@ match prev_index_to_index[prev_index] { Some(dep_node_index) => dep_node_index, None => { - let mut data = self.data.lock(); - let dep_node_index = data.hybrid_indices.push(prev_index.into()); + let key = prev_graph.index_to_node(prev_index); + let dep_node_index = self.encoder.borrow().send( + profiler, + key, + prev_graph.fingerprint_by_index(prev_index), + prev_graph + .edge_targets_from(prev_index) + .iter() + .map(|i| prev_index_to_index[*i].unwrap()) + .collect(), + ); prev_index_to_index[prev_index] = Some(dep_node_index); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); dep_node_index } } @@ -1642,18 +1123,6 @@ } } -#[inline] -fn add_edges( - edges: &mut IndexVec, - edge_indices: &mut IndexVec>, - new_edges: EdgesVec, -) { - let start = edges.next_index(); - edges.extend(new_edges); - let end = edges.next_index(); - edge_indices.push(start..end); -} - /// The capacity of the `reads` field `SmallVec` const TASK_DEPS_READS_CAP: usize = 8; type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/mod.rs 2021-06-17 03:53:50.000000000 +0000 @@ -13,6 +13,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; +use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; use std::fmt; @@ -59,7 +60,7 @@ } /// Describe the different families of dependency nodes. -pub trait DepKind: Copy + fmt::Debug + Eq + Hash { +pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { const NULL: Self; /// Return whether this kind always require evaluation. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/prev.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/prev.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/prev.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/prev.rs 2021-06-17 03:53:50.000000000 +0000 @@ -36,11 +36,6 @@ } #[inline] - pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { - self.index[dep_node] - } - - #[inline] pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { self.index.get(dep_node).cloned() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/query.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/query.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/query.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/query.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,38 +1,43 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::implementation::{Direction, Graph, NodeIndex, INCOMING}; +use rustc_index::vec::IndexVec; -use super::{DepKind, DepNode}; +use super::{DepKind, DepNode, DepNodeIndex}; pub struct DepGraphQuery { pub graph: Graph, ()>, pub indices: FxHashMap, NodeIndex>, + pub dep_index_to_index: IndexVec>, } impl DepGraphQuery { - pub fn new( - nodes: &[DepNode], - edge_list_indices: &[(usize, usize)], - edge_list_data: &[usize], - ) -> DepGraphQuery { - let mut graph = Graph::with_capacity(nodes.len(), edge_list_data.len()); - let mut indices = FxHashMap::default(); - for node in nodes { - indices.insert(*node, graph.add_node(*node)); + pub fn new(prev_node_count: usize) -> DepGraphQuery { + let node_count = prev_node_count + prev_node_count / 4; + let edge_count = 6 * node_count; + + let graph = Graph::with_capacity(node_count, edge_count); + let indices = FxHashMap::default(); + let dep_index_to_index = IndexVec::new(); + + DepGraphQuery { graph, indices, dep_index_to_index } + } + + pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { + let source = self.graph.add_node(node); + if index.index() >= self.dep_index_to_index.len() { + self.dep_index_to_index.resize(index.index() + 1, None); } + self.dep_index_to_index[index] = Some(source); + self.indices.insert(node, source); - for (source, &(start, end)) in edge_list_indices.iter().enumerate() { - for &target in &edge_list_data[start..end] { - let source = indices[&nodes[source]]; - let target = indices[&nodes[target]]; - graph.add_edge(source, target, ()); + for &target in edges.iter() { + let target = self.dep_index_to_index[target]; + // We may miss the edges that are pushed while the `DepGraphQuery` is being accessed. + // Skip them to issues. + if let Some(target) = target { + self.graph.add_edge(source, target, ()); } } - - DepGraphQuery { graph, indices } - } - - pub fn contains_node(&self, node: &DepNode) -> bool { - self.indices.contains_key(&node) } pub fn nodes(&self) -> Vec<&DepNode> { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/serialized.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/serialized.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/serialized.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/dep_graph/serialized.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,9 +1,28 @@ //! The data that we will serialize and deserialize. +//! +//! The dep-graph is serialized as a sequence of NodeInfo, with the dependencies +//! specified inline. The total number of nodes and edges are stored as the last +//! 16 bytes of the file, so we can find them easily at decoding time. +//! +//! The serialisation is performed on-demand when each node is emitted. Using this +//! scheme, we do not need to keep the current graph in memory. +//! +//! The deserisalisation is performed manually, in order to convert from the stored +//! sequence of NodeInfos to the different arrays in SerializedDepGraph. Since the +//! node and edge count are stored at the end of the file, all the arrays can be +//! pre-allocated with the right length. -use super::{DepKind, DepNode}; +use super::query::DepGraphQuery; +use super::{DepKind, DepNode, DepNodeIndex}; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_index::vec::IndexVec; -use rustc_serialize::{Decodable, Decoder}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::Lock; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}; +use rustc_serialize::{Decodable, Decoder, Encodable}; +use smallvec::SmallVec; +use std::convert::TryInto; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits // unused so that we can store multiple index types in `CompressedHybridIndex`, @@ -50,78 +69,239 @@ } } -impl> Decodable for SerializedDepGraph { - fn decode(d: &mut D) -> Result, D::Error> { - // We used to serialize the dep graph by creating and serializing a `SerializedDepGraph` - // using data copied from the `DepGraph`. But copying created a large memory spike, so we - // now serialize directly from the `DepGraph` as if it's a `SerializedDepGraph`. Because we - // deserialize that data into a `SerializedDepGraph` in the next compilation session, we - // need `DepGraph`'s `Encodable` and `SerializedDepGraph`'s `Decodable` implementations to - // be in sync. If you update this decoding, be sure to update the encoding, and vice-versa. - // - // We mimic the sequence of `Encode` and `Encodable` method calls used by the `DepGraph`'s - // `Encodable` implementation with the corresponding sequence of `Decode` and `Decodable` - // method calls. E.g. `Decode::read_struct` pairs with `Encode::emit_struct`, `DepNode`'s - // `decode` pairs with `DepNode`'s `encode`, and so on. Any decoding methods not associated - // with corresponding encoding methods called in `DepGraph`'s `Encodable` implementation - // are off limits, because we'd be relying on their implementation details. - // - // For example, because we know it happens to do the right thing, its tempting to just use - // `IndexVec`'s `Decodable` implementation to decode into some of the collections below, - // even though `DepGraph` doesn't use its `Encodable` implementation. But the `IndexVec` - // implementation could change, and we'd have a bug. - // - // Variables below are explicitly typed so that anyone who changes the `SerializedDepGraph` - // representation without updating this function will encounter a compilation error, and - // know to update this and possibly the `DepGraph` `Encodable` implementation accordingly - // (the latter should serialize data in a format compatible with our representation). - - d.read_struct("SerializedDepGraph", 4, |d| { - let nodes: IndexVec> = - d.read_struct_field("nodes", 0, |d| { - d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; +impl<'a, K: DepKind + Decodable>> Decodable> + for SerializedDepGraph +{ + #[instrument(skip(d))] + fn decode(d: &mut opaque::Decoder<'a>) -> Result, String> { + let start_position = d.position(); + + // The last 16 bytes are the node count and edge count. + debug!("position: {:?}", d.position()); + d.set_position(d.data.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE); + debug!("position: {:?}", d.position()); + + let node_count = IntEncodedWithFixedSize::decode(d)?.0 as usize; + let edge_count = IntEncodedWithFixedSize::decode(d)?.0 as usize; + debug!(?node_count, ?edge_count); + + debug!("position: {:?}", d.position()); + d.set_position(start_position); + debug!("position: {:?}", d.position()); + + let mut nodes = IndexVec::with_capacity(node_count); + let mut fingerprints = IndexVec::with_capacity(node_count); + let mut edge_list_indices = IndexVec::with_capacity(node_count); + let mut edge_list_data = Vec::with_capacity(edge_count); + + for _index in 0..node_count { + d.read_struct("NodeInfo", 3, |d| { + let dep_node: DepNode = d.read_struct_field("node", 0, Decodable::decode)?; + let _i: SerializedDepNodeIndex = nodes.push(dep_node); + debug_assert_eq!(_i.index(), _index); + + let fingerprint: Fingerprint = + d.read_struct_field("fingerprint", 1, Decodable::decode)?; + let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint); + debug_assert_eq!(_i.index(), _index); - let fingerprints: IndexVec = - d.read_struct_field("fingerprints", 1, |d| { + d.read_struct_field("edges", 2, |d| { d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); + let start = edge_list_data.len().try_into().unwrap(); + for e in 0..len { + let edge = d.read_seq_elt(e, Decodable::decode)?; + edge_list_data.push(edge); } - Ok(v) + let end = edge_list_data.len().try_into().unwrap(); + let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end)); + debug_assert_eq!(_i.index(), _index); + Ok(()) }) - })?; + }) + })?; + } - let edge_list_indices: IndexVec = d - .read_struct_field("edge_list_indices", 2, |d| { - d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; + Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data }) + } +} - let edge_list_data: Vec = - d.read_struct_field("edge_list_data", 3, |d| { - d.read_seq(|d, len| { - let mut v = Vec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; +#[derive(Debug, Encodable, Decodable)] +pub struct NodeInfo { + node: DepNode, + fingerprint: Fingerprint, + edges: SmallVec<[DepNodeIndex; 8]>, +} + +struct Stat { + kind: K, + node_counter: u64, + edge_counter: u64, +} + +struct EncoderState { + encoder: FileEncoder, + total_node_count: usize, + total_edge_count: usize, + result: FileEncodeResult, + stats: Option>>, +} + +impl EncoderState { + fn new(encoder: FileEncoder, record_stats: bool) -> Self { + Self { + encoder, + total_edge_count: 0, + total_node_count: 0, + result: Ok(()), + stats: if record_stats { Some(FxHashMap::default()) } else { None }, + } + } + + #[instrument(skip(self, record_graph))] + fn encode_node( + &mut self, + node: &NodeInfo, + record_graph: &Option>>, + ) -> DepNodeIndex { + let index = DepNodeIndex::new(self.total_node_count); + self.total_node_count += 1; + + let edge_count = node.edges.len(); + self.total_edge_count += edge_count; + + if let Some(record_graph) = &record_graph { + // Do not ICE when a query is called from within `with_query`. + if let Some(record_graph) = &mut record_graph.try_lock() { + record_graph.push(index, node.node, &node.edges); + } + } + + if let Some(stats) = &mut self.stats { + let kind = node.node.kind; + + let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); + stat.node_counter += 1; + stat.edge_counter += edge_count as u64; + } + + debug!(?index, ?node); + let encoder = &mut self.encoder; + if self.result.is_ok() { + self.result = node.encode(encoder); + } + index + } + + fn finish(self) -> FileEncodeResult { + let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self; + let () = result?; + + let node_count = total_node_count.try_into().unwrap(); + let edge_count = total_edge_count.try_into().unwrap(); + + debug!(?node_count, ?edge_count); + debug!("position: {:?}", encoder.position()); + IntEncodedWithFixedSize(node_count).encode(&mut encoder)?; + IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?; + debug!("position: {:?}", encoder.position()); + // Drop the encoder so that nothing is written after the counts. + encoder.flush() + } +} + +pub struct GraphEncoder { + status: Lock>, + record_graph: Option>>, +} + +impl> GraphEncoder { + pub fn new( + encoder: FileEncoder, + prev_node_count: usize, + record_graph: bool, + record_stats: bool, + ) -> Self { + let record_graph = + if record_graph { Some(Lock::new(DepGraphQuery::new(prev_node_count))) } else { None }; + let status = Lock::new(EncoderState::new(encoder, record_stats)); + GraphEncoder { status, record_graph } + } + + pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + if let Some(record_graph) = &self.record_graph { + f(&record_graph.lock()) + } + } + + pub(crate) fn print_incremental_info( + &self, + total_read_count: u64, + total_duplicate_read_count: u64, + ) { + let status = self.status.lock(); + if let Some(record_stats) = &status.stats { + let mut stats: Vec<_> = record_stats.values().collect(); + stats.sort_by_key(|s| -(s.node_counter as i64)); + + const SEPARATOR: &str = "[incremental] --------------------------------\ + ----------------------------------------------\ + ------------"; + + eprintln!("[incremental]"); + eprintln!("[incremental] DepGraph Statistics"); + eprintln!("{}", SEPARATOR); + eprintln!("[incremental]"); + eprintln!("[incremental] Total Node Count: {}", status.total_node_count); + eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count); + + if cfg!(debug_assertions) { + eprintln!("[incremental] Total Edge Reads: {}", total_read_count); + eprintln!( + "[incremental] Total Duplicate Edge Reads: {}", + total_duplicate_read_count + ); + } + + eprintln!("[incremental]"); + eprintln!( + "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", + "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" + ); + eprintln!("{}", SEPARATOR); + + for stat in stats { + let node_kind_ratio = + (100.0 * (stat.node_counter as f64)) / (status.total_node_count as f64); + let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); + + eprintln!( + "[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", + format!("{:?}", stat.kind), + node_kind_ratio, + stat.node_counter, + node_kind_avg_edges, + ); + } + + eprintln!("{}", SEPARATOR); + eprintln!("[incremental]"); + } + } + + pub(crate) fn send( + &self, + profiler: &SelfProfilerRef, + node: DepNode, + fingerprint: Fingerprint, + edges: SmallVec<[DepNodeIndex; 8]>, + ) -> DepNodeIndex { + let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); + let node = NodeInfo { node, fingerprint, edges }; + self.status.lock().encode_node(&node, &self.record_graph) + } - Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data }) - }) + pub fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { + let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); + self.status.into_inner().finish() } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,8 +1,9 @@ #![feature(bool_to_option)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(core_intrinsics)] +#![feature(drain_filter)] #![feature(hash_raw_entry)] +#![feature(iter_zip)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/caches.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/caches.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/caches.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/caches.rs 2021-06-17 03:53:50.000000000 +0000 @@ -49,13 +49,11 @@ index: DepNodeIndex, ) -> Self::Stored; - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce( - &'a mut dyn Iterator, - ) -> R, - ) -> R; + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ); } pub struct DefaultCacheSelector; @@ -124,14 +122,17 @@ value } - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce(&'a mut dyn Iterator) -> R, - ) -> R { + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ) { let shards = shards.lock_shards(); - let mut results = shards.iter().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1)); - f(&mut results) + for shard in shards.iter() { + for (k, v) in shard.iter() { + f(k, &v.0, v.1); + } + } } } @@ -207,13 +208,16 @@ &value.0 } - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce(&'a mut dyn Iterator) -> R, - ) -> R { + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ) { let shards = shards.lock_shards(); - let mut results = shards.iter().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1)); - f(&mut results) + for shard in shards.iter() { + for (k, v) in shard.iter() { + f(k, &v.0, v.1); + } + } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/job.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/job.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/job.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/job.rs 2021-06-17 03:53:50.000000000 +0000 @@ -22,7 +22,7 @@ rustc_data_structures::{jobserver, OnDrop}, rustc_rayon_core as rayon_core, rustc_span::DUMMY_SP, - std::iter::FromIterator, + std::iter::{self, FromIterator}, std::{mem, process}, }; @@ -463,7 +463,7 @@ spans.rotate_right(1); // Zip them back together - let mut stack: Vec<_> = spans.into_iter().zip(queries).collect(); + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); // Remove the queries in our cycle from the list of jobs to look at for r in &stack { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/plumbing.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/plumbing.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_query_system/src/query/plumbing.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_query_system/src/query/plumbing.rs 2021-06-17 03:53:50.000000000 +0000 @@ -73,12 +73,7 @@ (QueryLookup { key_hash, shard }, lock) } - pub fn iter_results( - &self, - f: impl for<'a> FnOnce( - &'a mut dyn Iterator, - ) -> R, - ) -> R { + pub fn iter_results(&self, f: &mut dyn FnMut(&C::Key, &C::Value, DepNodeIndex)) { self.cache.iter(&self.shards, f) } } @@ -449,9 +444,11 @@ let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { tcx.start_query(job.id, diagnostics, || { - tcx.dep_context() - .dep_graph() - .with_anon_task(query.dep_kind, || query.compute(tcx, key)) + tcx.dep_context().dep_graph().with_anon_task( + *tcx.dep_context(), + query.dep_kind, + || query.compute(tcx, key), + ) }) }); @@ -537,7 +534,7 @@ // If `-Zincremental-verify-ich` is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) { - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, dep_node_index, query); + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); } result @@ -560,7 +557,7 @@ // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, dep_node_index, query); + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); result } @@ -570,14 +567,12 @@ tcx: CTX::DepContext, result: &V, dep_node: &DepNode, - dep_node_index: DepNodeIndex, query: &QueryVtable, ) where CTX: QueryContext, { assert!( - Some(tcx.dep_graph().fingerprint_of(dep_node_index)) - == tcx.dep_graph().prev_fingerprint_of(dep_node), + tcx.dep_graph().is_green(dep_node), "fingerprint for green query instance not loaded from cache: {:?}", dep_node, ); @@ -588,9 +583,9 @@ let new_hash = query.hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO); debug!("END verify_ich({:?})", dep_node); - let old_hash = tcx.dep_graph().fingerprint_of(dep_node_index); + let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); - if new_hash != old_hash { + if Some(new_hash) != old_hash { let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { format!("`cargo clean -p {}` or `cargo clean`", crate_name) } else { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/build_reduced_graph.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/build_reduced_graph.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/build_reduced_graph.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/build_reduced_graph.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1230,13 +1230,13 @@ }; let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id()); - let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); self.r.macro_map.insert(def_id.to_def_id(), ext); self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); - if macro_rules && matches!(item.vis.kind, ast::VisibilityKind::Inherited) { + if macro_rules { let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); + let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { ty::Visibility::Public } else { @@ -1261,11 +1261,6 @@ }), )) } else { - if is_macro_export { - let what = if macro_rules { "`macro_rules` with `pub`" } else { "`macro` items" }; - let msg = format!("`#[macro_export]` cannot be used on {what}"); - self.r.session.span_err(item.span, &msg); - } let module = parent_scope.module; let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/diagnostics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/diagnostics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/diagnostics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/diagnostics.rs 2021-06-17 03:53:50.000000000 +0000 @@ -450,12 +450,12 @@ self.session, span, E0128, - "type parameters with a default cannot use \ + "generic parameters with a default cannot use \ forward declared identifiers" ); err.span_label( span, - "defaulted type parameters cannot be forward declared".to_string(), + "defaulted generic parameters cannot be forward declared".to_string(), ); err } @@ -472,17 +472,6 @@ ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, @@ -498,7 +487,13 @@ name )); } - err.help("use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions"); + + if self.session.is_nightly_build() { + err.help( + "use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` \ + to allow generic const expressions" + ); + } err } @@ -606,7 +601,7 @@ /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( &mut self, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, @@ -662,7 +657,7 @@ let root_module = this.resolve_crate_root(root_ident); this.add_module_candidates(root_module, &mut suggestions, filter_fn); } - Scope::Module(module) => { + Scope::Module(module, _) => { this.add_module_candidates(module, &mut suggestions, filter_fn); } Scope::RegisteredAttrs => { @@ -758,17 +753,14 @@ { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); - let not_local_module = crate_name.name != kw::Crate; - let mut worklist = - vec![(start_module, Vec::::new(), true, not_local_module)]; + let mut worklist = vec![(start_module, Vec::::new(), true)]; let mut worklist_via_import = vec![]; - while let Some((in_module, path_segments, accessible, in_module_is_extern)) = - match worklist.pop() { - None => worklist_via_import.pop(), - Some(x) => Some(x), - } - { + while let Some((in_module, path_segments, accessible)) = match worklist.pop() { + None => worklist_via_import.pop(), + Some(x) => Some(x), + } { + let in_module_is_extern = !in_module.def_id().unwrap().is_local(); // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -850,11 +842,10 @@ name_binding.is_extern_crate() && lookup_ident.span.rust_2018(); if !is_extern_crate_that_also_appears_in_prelude { - let is_extern = in_module_is_extern || name_binding.is_extern_crate(); // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { if via_import { &mut worklist_via_import } else { &mut worklist } - .push((module, path_segments, child_accessible, is_extern)); + .push((module, path_segments, child_accessible)); } } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/imports.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/imports.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/imports.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/imports.rs 2021-06-17 03:53:50.000000000 +0000 @@ -955,14 +955,14 @@ } return None; } - PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { + PathResult::NonModule(_) => { if no_ambiguity { assert!(import.imported_module.get().is_none()); } // The error was already reported earlier. return None; } - PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), + PathResult::Indeterminate => unreachable!(), }; let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late/diagnostics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late/diagnostics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late/diagnostics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late/diagnostics.rs 2021-06-17 03:53:50.000000000 +0000 @@ -22,6 +22,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use std::iter; + use tracing::debug; type Res = def::Res; @@ -184,7 +186,7 @@ PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(), _ => None, } - .map_or(String::new(), |res| format!("{} ", res.descr())); + .map_or_else(String::new, |res| format!("{} ", res.descr())); (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; ( @@ -454,12 +456,14 @@ } } + let is_macro = base_span.from_expansion() && base_span.desugaring_kind().is_none(); if !self.type_ascription_suggestion(&mut err, base_span) { let mut fallback = false; if let ( PathSource::Trait(AliasPossibility::Maybe), Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)), - ) = (source, res) + false, + ) = (source, res, is_macro) { if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { fallback = true; @@ -926,7 +930,14 @@ let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ `type` alias"; if let Some(span) = self.def_span(def_id) { - err.span_help(span, msg); + if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) { + // The span contains a type alias so we should be able to + // replace `type` with `trait`. + let snip = snip.replacen("type", "trait", 1); + err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect); + } else { + err.span_help(span, msg); + } } else { err.help(msg); } @@ -1004,9 +1015,7 @@ if let Some(spans) = field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len()) { - let non_visible_spans: Vec = fields - .iter() - .zip(spans.iter()) + let non_visible_spans: Vec = iter::zip(&fields, &spans) .filter(|(vis, _)| { !self.r.is_accessible_from(**vis, self.parent_scope.module) }) @@ -1042,10 +1051,10 @@ if let Some(span) = self.def_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } - let fields = - self.r.field_names.get(&def_id).map_or("/* fields */".to_string(), |fields| { - vec!["_"; fields.len()].join(", ") - }); + let fields = self.r.field_names.get(&def_id).map_or_else( + || "/* fields */".to_string(), + |fields| vec!["_"; fields.len()].join(", "), + ); err.span_suggestion( span, "use the tuple variant pattern syntax instead", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late/lifetimes.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late/lifetimes.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late/lifetimes.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late/lifetimes.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! Name resolution for lifetimes. //! //! Name resolution for lifetimes follows *much* simpler rules than the @@ -11,7 +12,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE}; +use rustc_hir::def_id::DefIdMap; use rustc_hir::hir_id::ItemLocalId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; @@ -26,9 +27,10 @@ use rustc_span::Span; use std::borrow::Cow; use std::cell::Cell; +use std::fmt; use std::mem::take; -use tracing::debug; +use tracing::{debug, span, Level}; // This counts the no of times a lifetime is used #[derive(Clone, Copy, Debug)] @@ -40,9 +42,9 @@ trait RegionExt { fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region); - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); + fn late(index: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); - fn late_anon(index: &Cell) -> Region; + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region; fn id(&self) -> Option; @@ -65,29 +67,32 @@ (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id(), origin)) } - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { + fn late(idx: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { let depth = ty::INNERMOST; let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); debug!( - "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", - param, depth, def_id, origin, + "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?} origin={:?}", + idx, param, depth, def_id, origin, ); - (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id.to_def_id(), origin)) + ( + param.name.normalize_to_macros_2_0(), + Region::LateBound(depth, idx, def_id.to_def_id(), origin), + ) } - fn late_anon(index: &Cell) -> Region { + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region { let i = index.get(); index.set(i + 1); let depth = ty::INNERMOST; - Region::LateBoundAnon(depth, i) + Region::LateBoundAnon(depth, named_late_bound_vars + i, i) } fn id(&self) -> Option { match *self { Region::Static | Region::LateBoundAnon(..) => None, - Region::EarlyBound(_, id, _) | Region::LateBound(_, id, _) | Region::Free(_, id) => { + Region::EarlyBound(_, id, _) | Region::LateBound(_, _, id, _) | Region::Free(_, id) => { Some(id) } } @@ -95,11 +100,11 @@ fn shifted(self, amount: u32) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_in(amount), id, origin) + Region::LateBound(debruijn, idx, id, origin) => { + Region::LateBound(debruijn.shifted_in(amount), idx, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_in(amount), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index) } _ => self, } @@ -107,11 +112,11 @@ fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_out_to_binder(binder), id, origin) + Region::LateBound(debruijn, index, id, origin) => { + Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index) } _ => self, } @@ -135,7 +140,7 @@ /// FIXME. This struct gets converted to a `ResolveLifetimes` for /// actual use. It has the same data, but indexed by `LocalDefId`. This /// is silly. -#[derive(Default)] +#[derive(Debug, Default)] struct NamedRegionMap { // maps from every use of a named (not anonymous) lifetime to a // `Region` describing how that region is bound @@ -146,9 +151,13 @@ // (b) it DOES appear in the arguments. late_bound: HirIdSet, - // For each type and trait definition, maps type parameters - // to the trait object lifetime defaults computed from them. - object_lifetime_defaults: HirIdMap>, + // Maps relevant hir items to the bound vars on them. These include: + // - function defs + // - function pointers + // - closures + // - trait refs + // - bound types (like `T` in `for<'a> T<'a>: Foo`) + late_bound_vars: HirIdMap>, } crate struct LifetimeContext<'a, 'tcx> { @@ -156,26 +165,16 @@ map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - /// This is slightly complicated. Our representation for poly-trait-refs contains a single - /// binder and thus we only allow a single level of quantification. However, - /// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>` - /// and `for <'a, 'b> &'b T: Foo<'a>`. In order to get the De Bruijn indices - /// correct when representing these constraints, we should only introduce one - /// scope. However, we want to support both locations for the quantifier and - /// during lifetime resolution we want precise information (so we can't - /// desugar in an earlier phase). - /// - /// So, if we encounter a quantifier at the outer scope, we set - /// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter - /// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`, - /// then we introduce the scope at the inner quantifier. - trait_ref_hack: bool, - /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, is_in_const_generic: bool, + /// Indicates that we only care about the definition of a trait. This should + /// be false if the `Item` we are resolving lifetimes for is not a trait or + /// we eventually need lifetimes resolve for trait items. + trait_definition_only: bool, + /// List of labels in the function/method currently under analysis. labels_in_fn: Vec, @@ -222,6 +221,14 @@ /// of the resulting opaque type. opaque_type_parent: bool, + scope_type: BinderScopeType, + + /// The late bound vars for a given item are stored by `HirId` to be + /// queried later. However, if we enter an elision scope, we have to + /// later append the elided bound vars to the list and need to know what + /// to append to. + hir_id: hir::HirId, + s: ScopeRef<'a>, }, @@ -249,14 +256,90 @@ s: ScopeRef<'a>, }, + /// When we have nested trait refs, we concanetate late bound vars for inner + /// trait refs from outer ones. But we also need to include any HRTB + /// lifetimes encountered when identifying the trait that an associated type + /// is declared on. + Supertrait { + lifetimes: Vec, + s: ScopeRef<'a>, + }, + + TraitRefBoundary { + s: ScopeRef<'a>, + }, + Root, } +#[derive(Copy, Clone, Debug)] +enum BinderScopeType { + /// Any non-concatenating binder scopes. + Normal, + /// Within a syntactic trait ref, there may be multiple poly trait refs that + /// are nested (under the `associcated_type_bounds` feature). The binders of + /// the innner poly trait refs are extended from the outer poly trait refs + /// and don't increase the late bound depth. If you had + /// `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'b>` scope + /// would be `Concatenating`. This also used in trait refs in where clauses + /// where we have two binders `for<> T: for<> Foo` (I've intentionally left + /// out any lifetimes because they aren't needed to show the two scopes). + /// The inner `for<>` has a scope of `Concatenating`. + Concatenating, +} + +// A helper struct for debugging scopes without printing parent scopes +struct TruncatedScopeDebug<'a>(&'a Scope<'a>); + +impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 { + Scope::Binder { + lifetimes, + next_early_index, + track_lifetime_uses, + opaque_type_parent, + scope_type, + hir_id, + s: _, + } => f + .debug_struct("Binder") + .field("lifetimes", lifetimes) + .field("next_early_index", next_early_index) + .field("track_lifetime_uses", track_lifetime_uses) + .field("opaque_type_parent", opaque_type_parent) + .field("scope_type", scope_type) + .field("hir_id", hir_id) + .field("s", &"..") + .finish(), + Scope::Body { id, s: _ } => { + f.debug_struct("Body").field("id", id).field("s", &"..").finish() + } + Scope::Elision { elide, s: _ } => { + f.debug_struct("Elision").field("elide", elide).field("s", &"..").finish() + } + Scope::ObjectLifetimeDefault { lifetime, s: _ } => f + .debug_struct("ObjectLifetimeDefault") + .field("lifetime", lifetime) + .field("s", &"..") + .finish(), + Scope::Supertrait { lifetimes, s: _ } => f + .debug_struct("Supertrait") + .field("lifetimes", lifetimes) + .field("s", &"..") + .finish(), + Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), + Scope::Root => f.debug_struct("Root").finish(), + } + } +} + #[derive(Clone, Debug)] enum Elide { /// Use a fresh anonymous late-bound lifetime each time, by - /// incrementing the counter to generate sequential indices. - FreshLateAnon(Cell), + /// incrementing the counter to generate sequential indices. All + /// anonymous lifetimes must start *after* named bound vars. + FreshLateAnon(u32, Cell), /// Always use this one lifetime. Exact(Region), /// Less or more than one lifetime were found, error on unspecified. @@ -283,26 +366,94 @@ pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { + resolve_lifetimes_trait_definition, resolve_lifetimes, - named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), + named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), is_late_bound_map, object_lifetime_defaults_map: |tcx, id| { - tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) + let hir_id = tcx.hir().local_def_id_to_hir_id(id); + match tcx.hir().find(hir_id) { + Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item), + _ => None, + } }, + late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), ..*providers }; } -/// Computes the `ResolveLifetimes` map that contains data for the -/// entire crate. You should not read the result of this query -/// directly, but rather use `named_region_map`, `is_late_bound_map`, -/// etc. -fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes { - assert_eq!(for_krate, LOCAL_CRATE); +/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items. +/// Also does not generate any diagnostics. +/// +/// This is ultimately a subset of the `resolve_lifetimes` work. It effectively +/// resolves lifetimes only within the trait "header" -- that is, the trait +/// and supertrait list. In contrast, `resolve_lifetimes` resolves all the +/// lifetimes within the trait and its items. There is room to refactor this, +/// for example to resolve lifetimes for each trait item in separate queries, +/// but it's convenient to do the entire trait at once because the lifetimes +/// from the trait definition are in scope within the trait items as well. +/// +/// The reason for this separate call is to resolve what would otherwise +/// be a cycle. Consider this example: +/// +/// ```rust +/// trait Base<'a> { +/// type BaseItem; +/// } +/// trait Sub<'b>: for<'a> Base<'a> { +/// type SubItem: Sub; +/// } +/// ``` +/// +/// When we resolve `Sub` and all its items, we also have to resolve `Sub`. +/// To figure out the index of `'b`, we have to know about the supertraits +/// of `Sub` so that we can determine that the `for<'a>` will be in scope. +/// (This is because we -- currently at least -- flatten all the late-bound +/// lifetimes into a single binder.) This requires us to resolve the +/// *trait definition* of `Sub`; basically just enough lifetime information +/// to look at the supertraits. +#[tracing::instrument(level = "debug", skip(tcx))] +fn resolve_lifetimes_trait_definition( + tcx: TyCtxt<'_>, + local_def_id: LocalDefId, +) -> ResolveLifetimes { + do_resolve(tcx, local_def_id, true) +} + +/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`. +/// You should not read the result of this query directly, but rather use +/// `named_region_map`, `is_late_bound_map`, etc. +#[tracing::instrument(level = "debug", skip(tcx))] +fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes { + do_resolve(tcx, local_def_id, false) +} - let named_region_map = krate(tcx); +fn do_resolve( + tcx: TyCtxt<'_>, + local_def_id: LocalDefId, + trait_definition_only: bool, +) -> ResolveLifetimes { + let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id)); + let mut named_region_map = NamedRegionMap { + defs: Default::default(), + late_bound: Default::default(), + late_bound_vars: Default::default(), + }; + let mut visitor = LifetimeContext { + tcx, + map: &mut named_region_map, + scope: ROOT_SCOPE, + is_in_fn_syntax: false, + is_in_const_generic: false, + trait_definition_only, + labels_in_fn: vec![], + xcrate_object_lifetime_defaults: Default::default(), + lifetime_uses: &mut Default::default(), + missing_named_lifetime_spots: vec![], + }; + visitor.visit_item(item); let mut rl = ResolveLifetimes::default(); @@ -314,14 +465,62 @@ let map = rl.late_bound.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id); } - for (hir_id, v) in named_region_map.object_lifetime_defaults { - let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default(); + for (hir_id, v) in named_region_map.late_bound_vars { + let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } + debug!(?rl.defs); rl } +/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution. +/// There are two important things this does. +/// First, we have to resolve lifetimes for +/// the entire *`Item`* that contains this owner, because that's the largest "scope" +/// where we can have relevant lifetimes. +/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition` +/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics. +/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner +/// other than the trait itself (like the trait methods or associated types), then we just use the regular +/// `resolve_lifetimes`. +fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes { + let item_id = item_for(tcx, def_id); + if item_id == def_id { + let item = tcx.hir().item(hir::ItemId { def_id: item_id }); + match item.kind { + hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id), + _ => tcx.resolve_lifetimes(item_id), + } + } else { + tcx.resolve_lifetimes(item_id) + } +} + +/// Finds the `Item` that contains the given `LocalDefId` +fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { + let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); + match tcx.hir().find(hir_id) { + Some(Node::Item(item)) => { + return item.def_id; + } + _ => {} + } + let item = { + let hir = tcx.hir(); + let mut parent_iter = hir.parent_iter(hir_id); + loop { + let node = parent_iter.next().map(|n| n.1); + match node { + Some(hir::Node::Item(item)) => break item.def_id, + Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."), + _ => {} + } + } + }; + item +} + fn is_late_bound_map<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -344,37 +543,10 @@ tcx.is_late_bound_map(def_id.expect_local()) } - _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)), + _ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)), } } -fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { - let krate = tcx.hir().krate(); - let mut map = NamedRegionMap { - defs: Default::default(), - late_bound: Default::default(), - object_lifetime_defaults: compute_object_lifetime_defaults(tcx), - }; - { - let mut visitor = LifetimeContext { - tcx, - map: &mut map, - scope: ROOT_SCOPE, - trait_ref_hack: false, - is_in_fn_syntax: false, - is_in_const_generic: false, - labels_in_fn: vec![], - xcrate_object_lifetime_defaults: Default::default(), - lifetime_uses: &mut Default::default(), - missing_named_lifetime_spots: vec![], - }; - for item in krate.items.values() { - visitor.visit_item(item); - } - } - map -} - /// In traits, there is an implicit `Self` type parameter which comes before the generics. /// We have to account for this when computing the index of the other generic parameters. /// This function returns whether there is such an implicit parameter defined on the given item. @@ -382,6 +554,56 @@ matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..)) } +fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind { + match region { + Region::LateBound(_, _, def_id, _) => { + let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + } + Region::LateBoundAnon(_, _, anon_idx) => { + ty::BoundVariableKind::Region(ty::BrAnon(*anon_idx)) + } + _ => bug!("{:?} is not a late region", region), + } +} + +impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { + /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. + fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { + let mut scope = self.scope; + let mut supertrait_lifetimes = vec![]; + loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break (vec![], BinderScopeType::Normal); + } + + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } + + Scope::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; + } + + Scope::TraitRefBoundary { .. } => { + // We should only see super trait lifetimes if there is a `Binder` above + assert!(supertrait_lifetimes.is_empty()); + break (vec![], BinderScopeType::Normal); + } + + Scope::Binder { hir_id, .. } => { + // Nested poly trait refs have the binders concatenated + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + break (full_binders, BinderScopeType::Concatenating); + } + } + } + } +} impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -392,6 +614,12 @@ // We want to nest trait/impl items in their parent, but nothing else. fn visit_nested_item(&mut self, _: hir::ItemId) {} + fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) { + if !self.trait_definition_only { + intravisit::walk_trait_item_ref(self, ii) + } + } + fn visit_nested_body(&mut self, body: hir::BodyId) { // Each body has their own set of labels, save labels. let saved = take(&mut self.labels_in_fn); @@ -403,11 +631,58 @@ self.labels_in_fn = saved; } + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'tcx>, + fd: &'tcx hir::FnDecl<'tcx>, + b: hir::BodyId, + s: rustc_span::Span, + 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(), + }; + let name: &str = &name; + let span = span!(Level::DEBUG, "visit_fn", name); + let _enter = span.enter(); + match fk { + // Any `Binders` are handled elsewhere + intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => { + intravisit::walk_fn(self, fk, fd, b, s, hir_id) + } + intravisit::FnKind::Closure => { + self.map.late_bound_vars.insert(hir_id, vec![]); + let scope = Scope::Binder { + hir_id, + lifetimes: FxHashMap::default(), + next_early_index: self.next_early_index(), + s: self.scope, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type: BinderScopeType::Normal, + }; + self.with(scope, move |_old_scope, this| { + intravisit::walk_fn(this, fk, fd, b, s, hir_id) + }); + } + } + } + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + match &item.kind { + hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { + if let Some(of_trait) = of_trait { + self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default()); + } + } + _ => {} + } match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { self.missing_named_lifetime_spots.push(generics.into()); - self.visit_early_late(None, &sig.decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| { intravisit::walk_item(this, item); }); self.missing_named_lifetime_spots.pop(); @@ -430,6 +705,47 @@ // Opaque types are visited when we visit the // `TyKind::OpaqueDef`, so that they have the lifetimes from // their parent opaque_ty in scope. + // + // The core idea here is that since OpaqueTys are generated with the impl Trait as + // their owner, we can keep going until we find the Item that owns that. We then + // conservatively add all resolved lifetimes. Otherwise we run into problems in + // cases like `type Foo<'a> = impl Bar`. + for (_hir_id, node) in + self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id)) + { + match node { + hir::Node::Item(parent_item) => { + let resolved_lifetimes: &ResolveLifetimes = + self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id)); + // We need to add *all* deps, since opaque tys may want them from *us* + for (&owner, defs) in resolved_lifetimes.defs.iter() { + defs.iter().for_each(|(&local_id, region)| { + self.map + .defs + .insert(hir::HirId { owner, local_id }, region.clone()); + }); + } + for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() { + late_bound.iter().for_each(|&local_id| { + self.map.late_bound.insert(hir::HirId { owner, local_id }); + }); + } + for (&owner, late_bound_vars) in + resolved_lifetimes.late_bound_vars.iter() + { + late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { + self.map.late_bound_vars.insert( + hir::HirId { owner, local_id }, + late_bound_vars.clone(), + ); + }); + } + break; + } + hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"), + _ => {} + } + } } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) @@ -463,16 +779,22 @@ } }) .collect(); + self.map.late_bound_vars.insert(item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, + scope_type: BinderScopeType::Normal, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - intravisit::walk_item(this, item); + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, item); + }); }); self.missing_named_lifetime_spots.pop(); } @@ -482,7 +804,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { hir::ForeignItemKind::Fn(ref decl, _, ref generics) => { - self.visit_early_late(None, decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -495,9 +817,8 @@ } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty); - debug!("visit_ty: ty.kind={:?}", ty.kind); match ty.kind { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); @@ -515,21 +836,29 @@ }; self.missing_named_lifetime_spots .push(MissingLifetimeSpot::HigherRanked { span, span_type }); + let (lifetimes, binders): (FxHashMap, Vec<_>) = c + .generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + (pair, r) + }) + .unzip(); + self.map.late_bound_vars.insert(ty.hir_id, binders); let scope = Scope::Binder { - lifetimes: c - .generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(), + hir_id: ty.hir_id, + lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -541,10 +870,13 @@ self.is_in_fn_syntax = was_in_fn_syntax; } hir::TyKind::TraitObject(bounds, ref lifetime, _) => { - debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime); - for bound in bounds { - self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); - } + debug!(?bounds, ?lifetime, "TraitObject"); + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |_, this| { + for bound in bounds { + this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); + } + }); match lifetime.name { LifetimeName::Implicit => { // For types like `dyn Foo`, we should @@ -564,7 +896,7 @@ // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 - self.resolve_elided_lifetimes(vec![lifetime]) + self.resolve_elided_lifetimes(&[lifetime]) } LifetimeName::Param(_) | LifetimeName::Static => { // If the user wrote an explicit name, use that. @@ -596,9 +928,12 @@ // Elided lifetimes are not allowed in non-return // position impl Trait - let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope }; + let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |_, this| { - intravisit::walk_item(this, opaque_ty); + let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, opaque_ty); + }) }); return; @@ -627,7 +962,7 @@ // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).cloned(); - if let Some(Region::LateBound(_, def_id, _)) = def { + if let Some(Region::LateBound(_, _, def_id, _)) = def { if let Some(def_id) = def_id.as_local() { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB @@ -652,14 +987,16 @@ }; if !parent_is_item { - struct_span_err!( - self.tcx.sess, - lifetime.span, - E0657, - "`impl Trait` can only capture lifetimes \ - bound at the fn or impl level" - ) - .emit(); + if !self.trait_definition_only { + struct_span_err!( + self.tcx.sess, + lifetime.span, + E0657, + "`impl Trait` can only capture lifetimes \ + bound at the fn or impl level" + ) + .emit(); + } self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } @@ -670,7 +1007,7 @@ // We want to start our early-bound indices at the end of the parent scope, // not including any parent `impl Trait`s. let mut index = self.next_early_index_for_opaque_type(); - debug!("visit_ty: index = {}", index); + debug!(?index); let mut elision = None; let mut lifetimes = FxHashMap::default(); @@ -704,38 +1041,49 @@ } } let next_early_index = index + non_lifetime_count; + self.map.late_bound_vars.insert(ty.hir_id, vec![]); if let Some(elision_region) = elision { let scope = Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope }; self.with(scope, |_old_scope, this| { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + for bound in bounds { + this.visit_param_bound(bound); + } + }) }); }); } else { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, |_old_scope, this| { - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + for bound in bounds { + this.visit_param_bound(bound); + } + }) }); } } @@ -751,6 +1099,7 @@ let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(trait_item.hir_id())), + trait_item.hir_id(), &sig.decl, &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item), @@ -776,22 +1125,28 @@ } }) .collect(); + self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: trait_item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } - if let Some(ty) = ty { - this.visit_ty(ty); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + for bound in bounds { + this.visit_param_bound(bound); + } + if let Some(ty) = ty { + this.visit_ty(ty); + } + }) }); self.missing_named_lifetime_spots.pop(); } @@ -813,6 +1168,7 @@ let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id())), + impl_item.hir_id(), &sig.decl, &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item), @@ -825,7 +1181,7 @@ let mut index = self.next_early_index(); let mut non_lifetime_count = 0; debug!("visit_ty: index = {}", index); - let lifetimes = generics + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { @@ -838,17 +1194,23 @@ } }) .collect(); + self.map.late_bound_vars.insert(ty.hir_id, vec![]); let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - this.visit_generics(generics); - this.visit_ty(ty); + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + this.visit_ty(ty); + }) }); self.missing_named_lifetime_spots.pop(); } @@ -862,10 +1224,10 @@ } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref); if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(vec![lifetime_ref]); + self.resolve_elided_lifetimes(&[lifetime_ref]); return; } if lifetime_ref.is_static() { @@ -897,93 +1259,113 @@ } fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { - check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { - walk_list!(self, visit_param_bound, param.bounds); - if let Some(ref ty) = default { - self.visit_ty(&ty); - } - } - GenericParamKind::Const { ref ty, .. } => { - let was_in_const_generic = self.is_in_const_generic; - self.is_in_const_generic = true; - walk_list!(self, visit_param_bound, param.bounds); - self.visit_ty(&ty); - self.is_in_const_generic = was_in_const_generic; + if !self.trait_definition_only { + check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); + } + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |_, this| { + for param in generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => { + walk_list!(this, visit_param_bound, param.bounds); + if let Some(ref ty) = default { + this.visit_ty(&ty); + } + } + GenericParamKind::Const { ref ty, .. } => { + 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); + this.is_in_const_generic = was_in_const_generic; + } } } - } - for predicate in generics.where_clause.predicates { - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - ref bounded_ty, - bounds, - ref bound_generic_params, - .. - }) => { - let lifetimes: FxHashMap<_, _> = bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(); - if !lifetimes.is_empty() { - let next_early_index = self.next_early_index(); + for predicate in generics.where_clause.predicates { + match predicate { + &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + ref bounded_ty, + bounds, + ref bound_generic_params, + .. + }) => { + let (lifetimes, binders): (FxHashMap, Vec<_>) = + bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = + Region::late(late_bound_idx as u32, &this.tcx.hir(), param); + let r = late_region_as_bound_region(this.tcx, &pair.1); + (pair, r) + }) + .unzip(); + this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); + let next_early_index = this.next_early_index(); + // Even if there are no lifetimes defined here, we still wrap it in a binder + // scope. If there happens to be a nested poly trait ref (an error), that + // will be `Concatenating` anyways, so we don't have to worry about the depth + // being wrong. let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, lifetimes, - s: self.scope, + s: this.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; - let result = self.with(scope, |old_scope, this| { + this.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); - this.trait_ref_hack = true; walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = false; - }); - result - } else { - self.visit_ty(&bounded_ty); - walk_list!(self, visit_param_bound, bounds); + }) + } + &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + ref lifetime, + bounds, + .. + }) => { + this.visit_lifetime(lifetime); + walk_list!(this, visit_param_bound, bounds); + } + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { + this.visit_ty(lhs_ty); + this.visit_ty(rhs_ty); } - } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - ref lifetime, - bounds, - .. - }) => { - self.visit_lifetime(lifetime); - walk_list!(self, visit_param_bound, bounds); - } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.visit_ty(lhs_ty); - self.visit_ty(rhs_ty); } } - } + }) } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { match bound { - hir::GenericBound::LangItemTrait { .. } if !self.trait_ref_hack => { + hir::GenericBound::LangItemTrait(_, _, hir_id, _) => { + // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go + // through the regular poly trait ref code, so we don't get another + // chance to introduce a binder. For now, I'm keeping the existing logic + // of "if there isn't a Binder scope above us, add one", but I + // imagine there's a better way to go about this. + let (binders, scope_type) = self.poly_trait_ref_binder_info(); + + self.map.late_bound_vars.insert(*hir_id, binders); let scope = Scope::Binder { + hir_id: *hir_id, lifetimes: FxHashMap::default(), s: self.scope, next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, + scope_type, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1002,48 +1384,53 @@ let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - let trait_ref_hack = take(&mut self.trait_ref_hack); - if !trait_ref_hack - || trait_ref - .bound_generic_params - .iter() - .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) - { - if trait_ref_hack { - struct_span_err!( - self.tcx.sess, - trait_ref.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); - } - let next_early_index = self.next_early_index(); - let scope = Scope::Binder { - lifetimes: trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(), - s: self.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - }; - self.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); - walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); - this.visit_trait_ref(&trait_ref.trait_ref); + let next_early_index = self.next_early_index(); + let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); + + let initial_bound_vars = binders.len() as u32; + let mut lifetimes: FxHashMap = FxHashMap::default(); + let binders_iter = trait_ref + .bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late( + initial_bound_vars + late_bound_idx as u32, + &self.tcx.hir(), + param, + ); + let r = late_region_as_bound_region(self.tcx, &pair.1); + lifetimes.insert(pair.0, pair.1); + r }); - } else { - self.visit_trait_ref(&trait_ref.trait_ref); - } - self.trait_ref_hack = trait_ref_hack; + binders.extend(binders_iter); + + debug!(?binders); + self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); + + // Always introduce a scope here, even if this is in a where clause and + // we introduced the binders around the bounded Ty. In that case, we + // just reuse the concatenation functionality also present in nested trait + // refs. + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + lifetimes, + s: self.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type, + }; + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); + walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + this.visit_trait_ref(&trait_ref.trait_ref); + }); + if should_pop_missing_lt { self.missing_named_lifetime_spots.pop(); } @@ -1193,7 +1580,9 @@ match *scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } @@ -1224,56 +1613,53 @@ } } -fn compute_object_lifetime_defaults(tcx: TyCtxt<'_>) -> HirIdMap> { - let mut map = HirIdMap::default(); - for item in tcx.hir().krate().items.values() { - match item.kind { - 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::TyAlias(_, ref generics) - | hir::ItemKind::Trait(_, _, ref generics, ..) => { - let result = object_lifetime_defaults_for_item(tcx, generics); - - // Debugging aid. - let attrs = tcx.hir().attrs(item.hir_id()); - if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { - let object_lifetime_default_reprs: String = result - .iter() - .map(|set| match *set { - Set1::Empty => "BaseDefault".into(), - Set1::One(Region::Static) => "'static".into(), - Set1::One(Region::EarlyBound(mut i, _, _)) => generics - .params - .iter() - .find_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if i == 0 { - return Some(param.name.ident().to_string().into()); - } - i -= 1; - None +fn compute_object_lifetime_defaults( + tcx: TyCtxt<'_>, + item: &hir::Item<'_>, +) -> Option> { + match item.kind { + 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::TyAlias(_, ref generics) + | hir::ItemKind::Trait(_, _, ref generics, ..) => { + let result = object_lifetime_defaults_for_item(tcx, generics); + + // Debugging aid. + let attrs = tcx.hir().attrs(item.hir_id()); + if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { + let object_lifetime_default_reprs: String = result + .iter() + .map(|set| match *set { + Set1::Empty => "BaseDefault".into(), + Set1::One(Region::Static) => "'static".into(), + Set1::One(Region::EarlyBound(mut i, _, _)) => generics + .params + .iter() + .find_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if i == 0 { + return Some(param.name.ident().to_string().into()); } - _ => None, - }) - .unwrap(), - Set1::One(_) => bug!(), - Set1::Many => "Ambiguous".into(), - }) - .collect::>>() - .join(","); - tcx.sess.span_err(item.span, &object_lifetime_default_reprs); - } - - map.insert(item.hir_id(), result); + i -= 1; + None + } + _ => None, + }) + .unwrap(), + Set1::One(_) => bug!(), + Set1::Many => "Ambiguous".into(), + }) + .collect::>>() + .join(","); + tcx.sess.span_err(item.span, &object_lifetime_default_reprs); } - _ => {} + + Some(result) } + _ => None, } - map } /// Scan the bounds and where-clauses on parameters to extract bounds @@ -1389,18 +1775,22 @@ tcx: *tcx, map, scope: &wrap_scope, - trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, is_in_const_generic: self.is_in_const_generic, + trait_definition_only: self.trait_definition_only, labels_in_fn, xcrate_object_lifetime_defaults, lifetime_uses, missing_named_lifetime_spots, }; - debug!("entering scope {:?}", this.scope); - f(self.scope, &mut this); - this.check_uses_for_lifetimes_defined_by_scope(); - debug!("exiting scope {:?}", this.scope); + let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); + { + let _enter = span.enter(); + f(self.scope, &mut this); + if !self.trait_definition_only { + this.check_uses_for_lifetimes_defined_by_scope(); + } + } self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; @@ -1552,7 +1942,7 @@ .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::Free(_, def_id) => Some(*def_id), Region::LateBoundAnon(..) | Region::Static => None, @@ -1698,6 +2088,7 @@ fn visit_early_late( &mut self, parent_id: Option, + hir_id: hir::HirId, decl: &'tcx hir::FnDecl<'tcx>, generics: &'tcx hir::Generics<'tcx>, walk: F, @@ -1707,31 +2098,34 @@ insert_late_bound_lifetimes(self.map, decl, generics); // Find the start of nested early scopes, e.g., in methods. - let mut index = 0; + let mut next_early_index = 0; if let Some(parent_id) = parent_id { let parent = self.tcx.hir().expect_item(parent_id); if sub_items_have_self_param(&parent.kind) { - index += 1; // Self comes before lifetimes + next_early_index += 1; // Self comes before lifetimes } match parent.kind { hir::ItemKind::Trait(_, _, ref generics, ..) | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { - index += generics.params.len() as u32; + next_early_index += generics.params.len() as u32; } _ => {} } } let mut non_lifetime_count = 0; - let lifetimes = generics + let mut named_late_bound_vars = 0; + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { if self.map.late_bound.contains(¶m.hir_id) { - Some(Region::late(&self.tcx.hir(), param)) + let late_bound_idx = named_late_bound_vars; + named_late_bound_vars += 1; + Some(Region::late(late_bound_idx, &self.tcx.hir(), param)) } else { - Some(Region::early(&self.tcx.hir(), &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut next_early_index, param)) } } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { @@ -1740,14 +2134,35 @@ } }) .collect(); - let next_early_index = index + non_lifetime_count; + let next_early_index = next_early_index + non_lifetime_count; + let binders: Vec<_> = generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } + if self.map.late_bound.contains(¶m.hir_id) => + { + Some(param) + } + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + r + }) + .collect(); + self.map.late_bound_vars.insert(hir_id, binders); let scope = Scope::Binder { + hir_id, lifetimes, next_early_index, s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1770,7 +2185,9 @@ Scope::Binder { s, .. } | Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => scope = s, + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => scope = s, } } } @@ -1819,7 +2236,7 @@ break None; } - Scope::Binder { ref lifetimes, s, .. } => { + Scope::Binder { ref lifetimes, scope_type, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -1829,12 +2246,17 @@ } _ => bug!("expected LifetimeName::Param"), } - - late_depth += 1; + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -1859,10 +2281,10 @@ } // Check for fn-syntax conflicts with in-band lifetime definitions - if self.is_in_fn_syntax { + if !self.trait_definition_only && self.is_in_fn_syntax { match def { Region::EarlyBound(_, _, LifetimeDefOrigin::InBand) - | Region::LateBound(_, _, LifetimeDefOrigin::InBand) => { + | Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => { struct_span_err!( self.tcx.sess, lifetime_ref.span, @@ -1883,6 +2305,7 @@ | Region::LateBound( _, _, + _, LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, ) | Region::LateBoundAnon(..) @@ -1916,7 +2339,7 @@ } let mut elide_lifetimes = true; - let lifetimes = generic_args + let lifetimes: Vec<_> = generic_args .args .iter() .filter_map(|arg| match arg { @@ -1929,8 +2352,10 @@ _ => None, }) .collect(); + // We short-circuit here if all are elided in order to pluralize + // possible errors if elide_lifetimes { - self.resolve_elided_lifetimes(lifetimes); + self.resolve_elided_lifetimes(&lifetimes); } else { lifetimes.iter().for_each(|lt| self.visit_lifetime(lt)); } @@ -1983,7 +2408,9 @@ Scope::Binder { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -1991,45 +2418,47 @@ }; let map = &self.map; - let unsubst = if let Some(def_id) = def_id.as_local() { + let set_to_region = |set: &ObjectLifetimeDefault| match *set { + Set1::Empty => { + if in_body { + None + } else { + Some(Region::Static) + } + } + Set1::One(r) => { + let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }); + r.subst(lifetimes, map) + } + Set1::Many => None, + }; + if let Some(def_id) = def_id.as_local() { let id = self.tcx.hir().local_def_id_to_hir_id(def_id); - &map.object_lifetime_defaults[&id] + self.tcx.object_lifetime_defaults(id).unwrap().iter().map(set_to_region).collect() } else { let tcx = self.tcx; - self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { - tcx.generics_of(def_id) - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamDefKind::Type { object_lifetime_default, .. } => { - Some(object_lifetime_default) - } - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, - }) - .collect() - }) - }; - debug!("visit_segment_args: unsubst={:?}", unsubst); - unsubst - .iter() - .map(|set| match *set { - Set1::Empty => { - if in_body { - None - } else { - Some(Region::Static) - } - } - Set1::One(r) => { - let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { - GenericArg::Lifetime(lt) => Some(lt), - _ => None, - }); - r.subst(lifetimes, map) - } - Set1::Many => None, - }) - .collect() + self.xcrate_object_lifetime_defaults + .entry(def_id) + .or_insert_with(|| { + tcx.generics_of(def_id) + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamDefKind::Type { object_lifetime_default, .. } => { + Some(object_lifetime_default) + } + GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => None, + }) + .collect() + }) + .iter() + .map(set_to_region) + .collect() + } }); debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); @@ -2080,23 +2509,139 @@ let has_lifetime_parameter = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); - // Resolve lifetimes found in the type `XX` from `Item = XX` bindings. - for b in generic_args.bindings { + // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or + // in the trait ref `YY<...>` in `Item: YY<...>`. + for binding in generic_args.bindings { let scope = Scope::ObjectLifetimeDefault { lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) }, s: self.scope, }; - self.with(scope, |_, this| this.visit_assoc_type_binding(b)); + if let Some(type_def_id) = type_def_id { + let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes( + self.tcx, + type_def_id, + binding.ident, + ); + self.with(scope, |_, this| { + let scope = + Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope }; + this.with(scope, |_, this| this.visit_assoc_type_binding(binding)); + }); + } else { + self.with(scope, |_, this| this.visit_assoc_type_binding(binding)); + } + } + } + + /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the + /// associated type name and starting trait. + /// For example, imagine we have + /// ```rust + /// trait Foo<'a, 'b> { + /// type As; + /// } + /// trait Bar<'b>: for<'a> Foo<'a, 'b> {} + /// trait Bar: for<'b> Bar<'b> {} + /// ``` + /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on + /// the starting trait `Bar`, we would return `Some(['b, 'a])`. + fn supertrait_hrtb_lifetimes( + tcx: TyCtxt<'tcx>, + def_id: DefId, + assoc_name: Ident, + ) -> Option> { + let trait_defines_associated_type_named = |trait_def_id: DefId| { + tcx.associated_items(trait_def_id) + .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id) + .is_some() + }; + + use smallvec::{smallvec, SmallVec}; + let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> = + smallvec![(def_id, smallvec![])]; + let mut visited: FxHashSet = FxHashSet::default(); + loop { + let (def_id, bound_vars) = match stack.pop() { + Some(next) => next, + None => break None, + }; + // See issue #83753. If someone writes an associated type on a non-trait, just treat it as + // there being no supertrait HRTBs. + match tcx.def_kind(def_id) { + DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {} + _ => break None, + } + + if trait_defines_associated_type_named(def_id) { + break Some(bound_vars.into_iter().collect()); + } + let predicates = + tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); + let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { + let bound_predicate = pred.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(data, _) => { + // The order here needs to match what we would get from `subst_supertrait` + let pred_bound_vars = bound_predicate.bound_vars(); + let mut all_bound_vars = bound_vars.clone(); + all_bound_vars.extend(pred_bound_vars.iter()); + let super_def_id = data.trait_ref.def_id; + Some((super_def_id, all_bound_vars)) + } + _ => None, + } + }); + + let obligations = obligations.filter(|o| visited.insert(o.0)); + stack.extend(obligations); } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_fn_like_elision( &mut self, inputs: &'tcx [hir::Ty<'tcx>], output: Option<&'tcx hir::Ty<'tcx>>, ) { debug!("visit_fn_like_elision: enter"); - let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope }; + let mut scope = &*self.scope; + let hir_id = loop { + match scope { + Scope::Binder { hir_id, .. } => { + break *hir_id; + } + Scope::Body { id, .. } => break id.hir_id, + Scope::ObjectLifetimeDefault { ref s, .. } + | Scope::Elision { ref s, .. } + | Scope::Supertrait { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { + scope = *s; + } + Scope::Root => { + // See issue #83907. Just bail out from looking inside. + self.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + "In fn_like_elision without appropriate scope above", + ); + return; + } + } + }; + // While not strictly necessary, we gather anon lifetimes *before* actually + // visiting the argument types. + let mut gather = GatherAnonLifetimes { anon_count: 0 }; + for input in inputs { + gather.visit_ty(input); + } + let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default(); + let named_late_bound_vars = late_bound_vars.len() as u32; + late_bound_vars.extend( + (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))), + ); + let arg_scope = Scope::Elision { + elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)), + s: self.scope, + }; self.with(arg_scope, |_, this| { for input in inputs { this.visit_ty(input); @@ -2108,7 +2653,7 @@ None => return, }; - debug!("visit_fn_like_elision: determine output"); + debug!("determine output"); // Figure out if there's a body we can get argument names from, // and whether there's a `self` argument (treated specially). @@ -2274,11 +2819,10 @@ Elide::Error(arg_lifetimes) }; - debug!("visit_fn_like_elision: elide={:?}", elide); + debug!(?elide); let scope = Scope::Elision { elide, s: self.scope }; self.with(scope, |_, this| this.visit_ty(output)); - debug!("visit_fn_like_elision: exit"); struct GatherLifetimes<'a> { map: &'a NamedRegionMap, @@ -2352,21 +2896,60 @@ fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) { match lifetime { - Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _) + Region::LateBound(debruijn, _, _, _) + | Region::LateBoundAnon(debruijn, _, _) if debruijn < self.outer_index => { self.have_bound_regions = true; } _ => { + // FIXME(jackh726): nested trait refs? self.lifetimes.insert(lifetime.shifted_out_to_binder(self.outer_index)); } } } } } + + struct GatherAnonLifetimes { + anon_count: u32, + } + impl<'v> Visitor<'v> for GatherAnonLifetimes { + type Map = intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + // If we enter a `BareFn`, then we enter a *new* binding scope + if let hir::TyKind::BareFn(_) = ty.kind { + return; + } + intravisit::walk_ty(self, ty); + } + + fn visit_generic_args( + &mut self, + path_span: Span, + generic_args: &'v hir::GenericArgs<'v>, + ) { + // parenthesized args enter a new elison scope + if generic_args.parenthesized { + return; + } + intravisit::walk_generic_args(self, path_span, generic_args) + } + + fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { + if lifetime_ref.is_elided() { + self.anon_count += 1; + } + } + } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) { debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); if lifetime_refs.is_empty() { @@ -2385,7 +2968,7 @@ Scope::Root => break None, - Scope::Binder { s, ref lifetimes, .. } => { + Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -2393,15 +2976,20 @@ lifetime_spans.push(name.span); } } - late_depth += 1; + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } Scope::Elision { ref elide, ref s, .. } => { let lifetime = match *elide { - Elide::FreshLateAnon(ref counter) => { + Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(counter).shifted(late_depth); + let lifetime = Region::late_anon(named_late_bound_vars, counter) + .shifted(late_depth); + self.insert_lifetime(lifetime_ref, lifetime); } return; @@ -2422,7 +3010,8 @@ scope = s; } Scope::ObjectLifetimeDefault { ref s, .. } - | Scope::Elision { ref s, .. } => { + | Scope::Elision { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { scope = s; } _ => break, @@ -2438,7 +3027,9 @@ return; } - Scope::ObjectLifetimeDefault { s, .. } => { + Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -2547,8 +3138,11 @@ let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::Binder { s, .. } => { - late_depth += 1; + Scope::Binder { s, scope_type, .. } => { + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -2557,6 +3151,10 @@ Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, + + Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { + scope = s; + } } }; self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth)); @@ -2680,7 +3278,9 @@ match *old_scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { old_scope = s; } @@ -2726,7 +3326,7 @@ // A lifetime only used in a fn argument could as well // be replaced with `'_`, as that would generate a // fresh name, too. - Scope::Elision { elide: Elide::FreshLateAnon(_), .. } => break true, + Scope::Elision { elide: Elide::FreshLateAnon(..), .. } => break true, // In the return type or other such place, `'_` is not // going to make a fresh name, so we cannot @@ -2736,17 +3336,18 @@ elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, .. } => break false, - Scope::ObjectLifetimeDefault { s, .. } => scope = s, + Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => scope = s, } } } + #[tracing::instrument(level = "debug", skip(self))] fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) { debug!( - "insert_lifetime: {} resolved to {:?} span={:?}", - self.tcx.hir().node_to_string(lifetime_ref.hir_id), - def, - self.tcx.sess.source_map().span_to_string(lifetime_ref.span) + node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id), + span = ?self.tcx.sess.source_map().span_to_string(lifetime_ref.span) ); self.map.defs.insert(lifetime_ref.hir_id, def); @@ -2756,16 +3357,16 @@ } Region::Free(_, def_id) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::EarlyBound(_, def_id, _) => { // A lifetime declared by the user. let track_lifetime_uses = self.track_lifetime_uses(); - debug!("insert_lifetime: track_lifetime_uses={}", track_lifetime_uses); + debug!(?track_lifetime_uses); if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) { - debug!("insert_lifetime: first use of {:?}", def_id); + debug!("first use of {:?}", def_id); self.lifetime_uses.insert(def_id, LifetimeUseSet::One(lifetime_ref)); } else { - debug!("insert_lifetime: many uses of {:?}", def_id); + debug!("many uses of {:?}", def_id); self.lifetime_uses.insert(def_id, LifetimeUseSet::Many); } } @@ -2791,13 +3392,12 @@ /// "Constrained" basically means that it appears in any type but /// not amongst the inputs to a projection. In other words, `<&'a /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`. +#[tracing::instrument(level = "debug", skip(map))] fn insert_late_bound_lifetimes( map: &mut NamedRegionMap, decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>, ) { - debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics); - let mut constrained_by_input = ConstrainedCollector::default(); for arg_ty in decl.inputs { constrained_by_input.visit_ty(arg_ty); @@ -2806,7 +3406,7 @@ let mut appears_in_output = AllCollector::default(); intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output); - debug!("insert_late_bound_lifetimes: constrained_by_input={:?}", constrained_by_input.regions); + debug!(?constrained_by_input.regions); // Walk the lifetimes that appear in where clauses. // @@ -2826,10 +3426,7 @@ } } - debug!( - "insert_late_bound_lifetimes: appears_in_where_clause={:?}", - appears_in_where_clause.regions - ); + debug!(?appears_in_where_clause.regions); // Late bound regions are those that: // - appear in the inputs @@ -2856,11 +3453,7 @@ continue; } - debug!( - "insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound", - param.name.ident(), - param.hir_id - ); + debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id); let inserted = map.late_bound.insert(param.hir_id); assert!(inserted, "visited lifetime {:?} twice", param.hir_id); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/late.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/late.rs 2021-06-17 03:53:50.000000000 +0000 @@ -132,10 +132,10 @@ /// We passed through a `macro_rules!` statement MacroDefinition(DefId), - /// All bindings in this rib are type parameters that can't be used - /// from the default of a type parameter because they're not declared - /// before said type parameter. Also see the `visit_generics` override. - ForwardTyParamBanRibKind, + /// All bindings in this rib are generic parameters that can't be used + /// from the default of a generic parameter because they're not declared + /// before said generic parameter. Also see the `visit_generics` override. + ForwardGenericParamBanRibKind, /// We are inside of the type of a const parameter. Can't refer to any /// parameters. @@ -154,7 +154,7 @@ | ModuleRibKind(_) | MacroDefinition(_) | ConstParamTyRibKind => false, - AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true, + AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, } } } @@ -555,17 +555,23 @@ // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Const { .. } | GenericParamKind::Lifetime { .. } => None, - GenericParamKind::Type { ref default, .. } => { - found_default |= default.is_some(); - found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - }, - )); + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -578,7 +584,7 @@ // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -590,32 +596,38 @@ } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| { - // HACK: We use an empty `ForwardTyParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } @@ -865,7 +877,7 @@ | ItemRibKind(..) | ConstantItemRibKind(..) | ModuleRibKind(..) - | ForwardTyParamBanRibKind + | ForwardGenericParamBanRibKind | ConstParamTyRibKind => { return false; } @@ -1030,7 +1042,6 @@ } ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { - debug!("resolve_item ItemKind::Const"); self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); if let Some(expr) = expr { @@ -1596,6 +1607,7 @@ .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); self.r.record_partial_res(pat.id, PartialRes::new(res)); + self.r.record_pat_span(pat.id, pat.span); } PatKind::TupleStruct(ref path, ref sub_patterns) => { self.smart_resolve_path( @@ -2326,7 +2338,7 @@ ExprKind::Call(ref callee, ref arguments) => { self.resolve_expr(callee, Some(expr)); - let const_args = self.r.legacy_const_generic_args(callee).unwrap_or(Vec::new()); + let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); for (idx, argument) in arguments.iter().enumerate() { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -6,7 +6,7 @@ //! Paths in macros, imports, expressions, types, patterns are resolved here. //! Label and lifetime names are resolved here as well. //! -//! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`. +//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] @@ -14,9 +14,11 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] +#![allow(rustdoc::private_intra_doc_links)] pub use rustc_hir::def::{Namespace, PerNS}; @@ -25,7 +27,6 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; -use rustc_ast::unwrap_or; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast::{Crate, CRATE_NODE_ID}; @@ -37,19 +38,19 @@ use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; -use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; -use rustc_hir::{PrimTy, TraitCandidate}; +use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, DefIdTree, ResolverOutputs}; +use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -108,7 +109,9 @@ DeriveHelpersCompat, MacroRules(MacroRulesScopeRef<'a>), CrateRoot, - Module(Module<'a>), + // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + // lint if it should be reported. + Module(Module<'a>, Option), RegisteredAttrs, MacroUsePrelude, BuiltinAttrs, @@ -122,13 +125,17 @@ /// with different restrictions when looking up the resolution. /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. -enum ScopeSet { +#[derive(Clone, Copy)] +enum ScopeSet<'a> { /// All scopes with the given namespace. All(Namespace, /*is_import*/ bool), /// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros). AbsolutePath(Namespace), /// All scopes with macro namespace and the given macro kind restriction. Macro(MacroKind), + /// All scopes with the given namespace, used for partially performing late resolution. + /// The node id enables lints and is used for reporting them. + Late(Namespace, Module<'a>, Option), } /// Everything you need to know about a name's location to resolve it. @@ -228,17 +235,15 @@ ), /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>), - /// Error E0128: type parameters with a default cannot use forward-declared identifiers. + /// Error E0128: generic parameters with a default cannot use forward-declared identifiers. ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { name: Symbol, is_type: bool }, - /// Error E0735: type parameters with a default cannot use `Self` + /// Error E0735: generic parameters with a default cannot use `Self` SelfInTyParamDefault, /// Error E0767: use of unreachable label UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option }, @@ -845,6 +850,12 @@ AlreadySeen(Span), } +struct DeriveData { + resolutions: DeriveResolutions, + helper_attrs: Vec<(usize, Ident)>, + has_derive_copy: bool, +} + /// The main resolver class. /// /// This is the visitor that walks the whole crate. @@ -878,6 +889,10 @@ /// "self-confirming" import resolutions during import validation. unusable_binding: Option<&'a NameBinding<'a>>, + // Spans for local variables found during pattern resolution. + // Used for suggestions during error reporting. + pat_span_map: NodeMap, + /// Resolutions for nodes that have a single resolution. partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. @@ -967,8 +982,9 @@ output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap>, - /// Resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`. - derive_resolutions: FxHashMap, ast::Path)>>, + /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute + /// with the given `ExpnId`. + derive_data: FxHashMap, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, @@ -1005,6 +1021,8 @@ trait_impl_items: FxHashSet, legacy_const_generic_args: FxHashMap>>, + + main_def: Option, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1256,6 +1274,7 @@ last_import_segment: false, unusable_binding: None, + pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), @@ -1304,7 +1323,7 @@ invocation_parent_scopes: Default::default(), output_macro_rules_scopes: Default::default(), helper_attrs: Default::default(), - derive_resolutions: Default::default(), + derive_data: Default::default(), local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), potentially_unused_imports: Vec::new(), @@ -1331,6 +1350,7 @@ next_disambiguator: Default::default(), trait_impl_items: Default::default(), legacy_const_generic_args: Default::default(), + main_def: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1365,6 +1385,7 @@ let maybe_unused_trait_imports = self.maybe_unused_trait_imports; let maybe_unused_extern_crates = self.maybe_unused_extern_crates; let glob_map = self.glob_map; + let main_def = self.main_def; ResolverOutputs { definitions, cstore: Box::new(self.crate_loader.into_cstore()), @@ -1379,6 +1400,7 @@ .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), + main_def, } } @@ -1397,6 +1419,7 @@ .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), + main_def: self.main_def.clone(), } } @@ -1442,6 +1465,7 @@ self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports()); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions()); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate)); + self.session.time("resolve_main", || self.resolve_main()); self.session.time("resolve_check_unused", || self.check_unused(krate)); self.session.time("resolve_report_errors", || self.report_errors(krate)); self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate)); @@ -1466,7 +1490,7 @@ self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| { match scope { - Scope::Module(module) => { + Scope::Module(module, _) => { this.traits_in_module(module, assoc_item, &mut found_traits); } Scope::StdLibPrelude => { @@ -1630,7 +1654,7 @@ /// If the callback returns `Some` result, we stop visiting scopes and return it. fn visit_scopes( &mut self, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, ctxt: SyntaxContext, mut visitor: impl FnMut( @@ -1686,12 +1710,17 @@ ScopeSet::All(ns, _) => (ns, None, false), ScopeSet::AbsolutePath(ns) => (ns, None, true), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Late(ns, ..) => (ns, None, false), + }; + let module = match scope_set { + // Start with the specified module. + ScopeSet::Late(_, module, _) => module, + // Jump out of trait or enum modules, they do not act as scopes. + _ => parent_scope.module.nearest_item_scope(), }; - // Jump out of trait or enum modules, they do not act as scopes. - let module = parent_scope.module.nearest_item_scope(); let mut scope = match ns { _ if is_absolute_path => Scope::CrateRoot, - TypeNS | ValueNS => Scope::Module(module), + TypeNS | ValueNS => Scope::Module(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ctxt = ctxt.normalize_to_macros_2_0(); @@ -1756,7 +1785,7 @@ MacroRulesScope::Invocation(invoc_id) => { Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules) } - MacroRulesScope::Empty => Scope::Module(module), + MacroRulesScope::Empty => Scope::Module(module, None), }, Scope::CrateRoot => match ns { TypeNS => { @@ -1765,10 +1794,16 @@ } ValueNS | MacroNS => break, }, - Scope::Module(module) => { + Scope::Module(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; - match self.hygienic_lexical_parent(module, &mut ctxt) { - Some(parent_module) => Scope::Module(parent_module), + let derive_fallback_lint_id = match scope_set { + ScopeSet::Late(.., lint_id) => lint_id, + _ => None, + }; + match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) { + Some((parent_module, lint_id)) => { + Scope::Module(parent_module, lint_id.or(prev_lint_id)) + } None => { ctxt.adjust(ExpnId::root()); match ns { @@ -1824,6 +1859,7 @@ ribs: &[Rib<'a>], ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); + let orig_ident = ident; if ident.name == kw::Empty { return Some(LexicalScopeBinding::Res(Res::Err)); } @@ -1873,135 +1909,48 @@ _ => continue, }; - let item = self.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - parent_scope, - record_used, - path_span, - ); - if let Ok(binding) = item { - // The ident resolves to an item. - return Some(LexicalScopeBinding::Item(binding)); - } - match module.kind { ModuleKind::Block(..) => {} // We can see through blocks _ => break, } - } - ident = normalized_ident; - let mut poisoned = None; - loop { - let mut span_data = ident.span.data(); - let opt_module = if let Some(node_id) = record_used_id { - self.hygienic_lexical_parent_with_compatibility_fallback( - module, - &mut span_data.ctxt, - node_id, - &mut poisoned, - ) - } else { - self.hygienic_lexical_parent(module, &mut span_data.ctxt) - }; - ident.span = span_data.span(); - module = unwrap_or!(opt_module, break); - let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; - let result = self.resolve_ident_in_module_unadjusted( + let item = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, ns, - adjusted_parent_scope, + parent_scope, record_used, path_span, ); - - match result { - Ok(binding) => { - if let Some(node_id) = poisoned { - self.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, - node_id, - ident.span, - &format!("cannot find {} `{}` in this scope", ns.descr(), ident), - BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span), - ); - } - return Some(LexicalScopeBinding::Item(binding)); - } - Err(Determined) => continue, - Err(Undetermined) => { - span_bug!(ident.span, "undetermined resolution during main resolution pass") - } - } - } - - if !module.no_implicit_prelude { - ident.span.adjust(ExpnId::root()); - if ns == TypeNS { - if let Some(binding) = self.extern_prelude_get(ident, !record_used) { - return Some(LexicalScopeBinding::Item(binding)); - } - if let Some(ident) = self.registered_tools.get(&ident) { - let binding = - (Res::ToolMod, ty::Visibility::Public, ident.span, ExpnId::root()) - .to_name_binding(self.arenas); - return Some(LexicalScopeBinding::Item(binding)); - } - } - if let Some(prelude) = self.prelude { - if let Ok(binding) = self.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(prelude), - ident, - ns, - parent_scope, - false, - path_span, - ) { - return Some(LexicalScopeBinding::Item(binding)); - } - } - } - - if ns == TypeNS { - if let Some(prim_ty) = PrimTy::from_name(ident.name) { - let binding = - (Res::PrimTy(prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) - .to_name_binding(self.arenas); + if let Ok(binding) = item { + // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); } } - - None + self.early_resolve_ident_in_lexical_scope( + orig_ident, + ScopeSet::Late(ns, module, record_used_id), + parent_scope, + record_used, + record_used, + path_span, + ) + .ok() + .map(LexicalScopeBinding::Item) } fn hygienic_lexical_parent( &mut self, module: Module<'a>, ctxt: &mut SyntaxContext, - ) -> Option> { + derive_fallback_lint_id: Option, + ) -> Option<(Module<'a>, Option)> { if !module.expansion.outer_expn_is_descendant_of(*ctxt) { - return Some(self.macro_def_scope(ctxt.remove_mark())); + return Some((self.macro_def_scope(ctxt.remove_mark()), None)); } if let ModuleKind::Block(..) = module.kind { - return Some(module.parent.unwrap().nearest_item_scope()); - } - - None - } - - fn hygienic_lexical_parent_with_compatibility_fallback( - &mut self, - module: Module<'a>, - ctxt: &mut SyntaxContext, - node_id: NodeId, - poisoned: &mut Option, - ) -> Option> { - if let module @ Some(..) = self.hygienic_lexical_parent(module, ctxt) { - return module; + return Some((module.parent.unwrap().nearest_item_scope(), None)); } // We need to support the next case under a deprecation warning @@ -2015,20 +1964,21 @@ // ---- end // ``` // So we have to fall back to the module's parent during lexical resolution in this case. - if let Some(parent) = module.parent { - // Inner module is inside the macro, parent module is outside of the macro. - if module.expansion != parent.expansion - && module.expansion.is_descendant_of(parent.expansion) - { - // The macro is a proc macro derive - if let Some(def_id) = module.expansion.expn_data().macro_def_id { - let ext = self.get_macro_by_def_id(def_id); - if ext.builtin_name.is_none() - && ext.macro_kind() == MacroKind::Derive - && parent.expansion.outer_expn_is_descendant_of(*ctxt) - { - *poisoned = Some(node_id); - return module.parent; + if derive_fallback_lint_id.is_some() { + if let Some(parent) = module.parent { + // Inner module is inside the macro, parent module is outside of the macro. + if module.expansion != parent.expansion + && module.expansion.is_descendant_of(parent.expansion) + { + // The macro is a proc macro derive + if let Some(def_id) = module.expansion.expn_data().macro_def_id { + let ext = self.get_macro_by_def_id(def_id); + if ext.builtin_name.is_none() + && ext.macro_kind() == MacroKind::Derive + && parent.expansion.outer_expn_is_descendant_of(*ctxt) + { + return Some((parent, derive_fallback_lint_id)); + } } } } @@ -2453,7 +2403,59 @@ .next() .map_or(false, |c| c.is_ascii_uppercase()) { - (format!("use of undeclared type `{}`", ident), None) + // Check whether the name refers to an item in the value namespace. + let suggestion = if ribs.is_some() { + let match_span = match self.resolve_ident_in_lexical_scope( + ident, + ValueNS, + parent_scope, + None, + path_span, + &ribs.unwrap()[ValueNS], + ) { + // Name matches a local variable. For example: + // ``` + // fn f() { + // let Foo: &str = ""; + // println!("{}", Foo::Bar); // Name refers to local + // // variable `Foo`. + // } + // ``` + Some(LexicalScopeBinding::Res(Res::Local(id))) => { + Some(*self.pat_span_map.get(&id).unwrap()) + } + + // Name matches item from a local name binding + // created by `use` declaration. For example: + // ``` + // pub Foo: &str = ""; + // + // mod submod { + // use super::Foo; + // println!("{}", Foo::Bar); // Name refers to local + // // binding `Foo`. + // } + // ``` + Some(LexicalScopeBinding::Item(name_binding)) => { + Some(name_binding.span) + } + _ => None, + }; + + if let Some(span) = match_span { + Some(( + vec![(span, String::from(""))], + format!("`{}` is defined here, but is not a type", ident), + Applicability::MaybeIncorrect, + )) + } else { + None + } + } else { + None + }; + + (format!("use of undeclared type `{}`", ident), suggestion) } else { (format!("use of undeclared crate or module `{}`", ident), None) } @@ -2592,8 +2594,8 @@ debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; - // An invalid forward use of a type parameter from a previous default. - if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind { + // An invalid forward use of a generic parameter from a previous default. + if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind { if record_used { let res_error = if rib_ident.name == kw::SelfUpper { ResolutionError::SelfInTyParamDefault @@ -2617,7 +2619,7 @@ | ClosureOrAsyncRibKind | ModuleRibKind(..) | MacroDefinition(..) - | ForwardTyParamBanRibKind => { + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2675,24 +2677,18 @@ } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2721,19 +2717,7 @@ } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2771,21 +2755,15 @@ ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2807,19 +2785,7 @@ return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, @@ -2860,6 +2826,11 @@ } } + fn record_pat_span(&mut self, node: NodeId, span: Span) { + debug!("(recording pat) recording {:?} for {:?}", node, span); + self.pat_span_map.insert(node, span); + } + fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { vis.is_accessible_from(module.nearest_parent_mod, self) } @@ -3386,6 +3357,32 @@ } None } + + fn resolve_main(&mut self) { + let module = self.graph_root; + let ident = Ident::with_dummy_span(sym::main); + let parent_scope = &ParentScope::module(module, self); + + let name_binding = match self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + ValueNS, + parent_scope, + false, + DUMMY_SP, + ) { + Ok(name_binding) => name_binding, + _ => return, + }; + + let res = name_binding.res(); + let is_import = name_binding.is_import(); + let span = name_binding.span; + if let Res::Def(DefKind::Fn, _) = res { + self.record_use(ident, ValueNS, name_binding, false); + } + self.main_def = Some(MainDefinition { res, is_import, span }); + } } fn names_to_string(names: &[Symbol]) -> String { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/macros.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/macros.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_resolve/src/macros.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_resolve/src/macros.rs 2021-06-17 03:53:50.000000000 +0000 @@ -4,7 +4,7 @@ use crate::imports::ImportResolver; use crate::Namespace::*; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy}; -use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; +use crate::{CrateLint, DeriveData, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId}; use rustc_ast_lowering::ResolverAstLowering; @@ -14,17 +14,18 @@ use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; -use rustc_expand::base::Annotatable; -use rustc_expand::base::{Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; +use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; -use rustc_expand::expand::{AstFragment, Invocation, InvocationKind}; +use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id; use rustc_hir::PrimTy; use rustc_middle::middle::stability; use rustc_middle::ty; -use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK}; +use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -278,12 +279,12 @@ // Derives are not included when `invocations` are collected, so we have to add them here. let parent_scope = &ParentScope { derives, ..parent_scope }; - let require_inert = !invoc.fragment_kind.supports_macro_expansion(); + let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion(); let node_id = self.lint_node_id(eager_expansion_root); let (ext, res) = self.smart_resolve_macro_path( path, kind, - require_inert, + supports_macro_expansion, inner_attr, parent_scope, node_id, @@ -358,8 +359,8 @@ fn resolve_derives( &mut self, expn_id: ExpnId, - derives: Vec, force: bool, + derive_paths: &dyn Fn() -> DeriveResolutions, ) -> Result<(), Indeterminate> { // Block expansion of the container until we resolve all derives in it. // This is required for two reasons: @@ -367,49 +368,63 @@ // is applied, so they have to be produced by the container's expansion rather // than by individual derives. // - Derives in the container need to know whether one of them is a built-in `Copy`. - // FIXME: Try to cache intermediate results to avoid resolving same derives multiple times. + // Temporarily take the data to avoid borrow checker conflicts. + let mut derive_data = mem::take(&mut self.derive_data); + let entry = derive_data.entry(expn_id).or_insert_with(|| DeriveData { + resolutions: derive_paths(), + helper_attrs: Vec::new(), + has_derive_copy: false, + }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - let mut exts = Vec::new(); - let mut helper_attrs = Vec::new(); - let mut has_derive_copy = false; - for path in derives { - exts.push(( - match self.resolve_macro_path( - &path, - Some(MacroKind::Derive), - &parent_scope, - true, - force, - ) { - Ok((Some(ext), _)) => { - let span = - path.segments.last().unwrap().ident.span.normalize_to_macros_2_0(); - helper_attrs - .extend(ext.helper_attrs.iter().map(|name| Ident::new(*name, span))); - has_derive_copy |= ext.builtin_name == Some(sym::Copy); - ext - } - Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), - Err(Determinacy::Undetermined) => return Err(Indeterminate), - }, - path, - )) + for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() { + if opt_ext.is_none() { + *opt_ext = Some( + match self.resolve_macro_path( + &path, + Some(MacroKind::Derive), + &parent_scope, + true, + force, + ) { + Ok((Some(ext), _)) => { + if !ext.helper_attrs.is_empty() { + let last_seg = path.segments.last().unwrap(); + let span = last_seg.ident.span.normalize_to_macros_2_0(); + entry.helper_attrs.extend( + ext.helper_attrs + .iter() + .map(|name| (i, Ident::new(*name, span))), + ); + } + entry.has_derive_copy |= ext.builtin_name == Some(sym::Copy); + ext + } + Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), + Err(Determinacy::Undetermined) => { + assert!(self.derive_data.is_empty()); + self.derive_data = derive_data; + return Err(Indeterminate); + } + }, + ); + } } - self.derive_resolutions.insert(expn_id, exts); - self.helper_attrs.insert(expn_id, helper_attrs); + // Sort helpers in a stable way independent from the derive resolution order. + entry.helper_attrs.sort_by_key(|(i, _)| *i); + self.helper_attrs + .insert(expn_id, entry.helper_attrs.iter().map(|(_, ident)| *ident).collect()); // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive // has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`. - if has_derive_copy || self.has_derive_copy(parent_scope.expansion) { + if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) { self.containers_deriving_copy.insert(expn_id); } + assert!(self.derive_data.is_empty()); + self.derive_data = derive_data; Ok(()) } - fn take_derive_resolutions( - &mut self, - expn_id: ExpnId, - ) -> Option, ast::Path)>> { - self.derive_resolutions.remove(&expn_id) + fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option { + self.derive_data.remove(&expn_id).map(|data| data.resolutions) } // The function that implements the resolution logic of `#[cfg_accessible(path)]`. @@ -457,7 +472,7 @@ &mut self, path: &ast::Path, kind: MacroKind, - require_inert: bool, + supports_macro_expansion: SupportsMacroExpansion, inner_attr: bool, parent_scope: &ParentScope<'a>, node_id: NodeId, @@ -505,8 +520,17 @@ let unexpected_res = if ext.macro_kind() != kind { Some((kind.article(), kind.descr_expected())) - } else if require_inert && matches!(res, Res::Def(..)) { - Some(("a", "non-macro attribute")) + } else if matches!(res, Res::Def(..)) { + match supports_macro_expansion { + SupportsMacroExpansion::No => Some(("a", "non-macro attribute")), + SupportsMacroExpansion::Yes { supports_inner_attrs } => { + if inner_attr && !supports_inner_attrs { + Some(("a", "non-macro inner attribute")) + } else { + None + } + } + } } else { None }; @@ -633,7 +657,7 @@ crate fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, record_used: bool, force: bool, @@ -660,6 +684,7 @@ ScopeSet::All(ns, is_import) => (ns, None, is_import), ScopeSet::AbsolutePath(ns) => (ns, None, false), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Late(ns, ..) => (ns, None, false), }; // This is *the* result, resolution from the scope closest to the resolved identifier. @@ -768,19 +793,34 @@ Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), } } - Scope::Module(module) => { + Scope::Module(module, derive_fallback_lint_id) => { let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let binding = this.resolve_ident_in_module_unadjusted_ext( ModuleOrUniformRoot::Module(module), ident, ns, adjusted_parent_scope, - true, + !matches!(scope_set, ScopeSet::Late(..)), record_used, path_span, ); match binding { Ok(binding) => { + if let Some(lint_id) = derive_fallback_lint_id { + this.lint_buffer.buffer_lint_with_diagnostic( + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + lint_id, + orig_ident.span, + &format!( + "cannot find {} `{}` in this scope", + ns.descr(), + ident + ), + BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback( + orig_ident.span, + ), + ); + } let misc_flags = if ptr::eq(module, this.graph_root) { Flags::MISC_SUGGEST_CRATE } else if module.is_normal() { @@ -864,7 +904,7 @@ Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => { - if !record_used { + if !record_used || matches!(scope_set, ScopeSet::Late(..)) { return Some(Ok(binding)); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/dump_visitor.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/dump_visitor.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/dump_visitor.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/dump_visitor.rs 2021-06-17 03:53:50.000000000 +0000 @@ -151,7 +151,7 @@ }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), external_crates: self.save_ctxt.get_external_crates(), - span: self.span_from_span(krate.item.span), + span: self.span_from_span(krate.item.inner), }; self.dumper.crate_prelude(data); @@ -320,15 +320,6 @@ for param in generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => { - return self - .nest_typeck_results(self.tcx.hir().local_def_id(param.hir_id), |this| { - this.visit_generics(generics) - }); - } hir::GenericParamKind::Type { .. } => { let param_ss = param.name.ident().span; let name = escape(self.span.snippet(param_ss)); @@ -1106,16 +1097,11 @@ format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id())); let sm = self.tcx.sess.source_map(); - let filename = sm.span_to_filename(krate.item.span); + let filename = sm.span_to_filename(krate.item.inner); let data_id = id_from_hir_id(id, &self.save_ctxt); - let children = krate - .item - .module - .item_ids - .iter() - .map(|i| id_from_def_id(i.def_id.to_def_id())) - .collect(); - let span = self.span_from_span(krate.item.span); + let children = + krate.item.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); + let span = self.span_from_span(krate.item.inner); let attrs = self.tcx.hir().attrs(id); self.dumper.dump_def( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] mod dump_visitor; @@ -516,19 +516,6 @@ }) } - pub fn get_trait_ref_data(&self, trait_ref: &hir::TraitRef<'_>) -> Option { - self.lookup_def_id(trait_ref.hir_ref_id).and_then(|def_id| { - let span = trait_ref.path.span; - if generated_code(span) { - return None; - } - let sub_span = trait_ref.path.segments.last().unwrap().ident.span; - filter!(self.span_utils, sub_span); - let span = self.span_from_span(sub_span); - Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }) - }) - } - pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option { let ty = self.typeck_results().expr_ty_adjusted_opt(expr)?; if matches!(ty.kind(), ty::Error(_)) { @@ -784,7 +771,10 @@ /// For a given piece of AST defined by the supplied Span and NodeId, /// returns `None` if the node is not macro-generated or the span is malformed, /// else uses the expansion callsite and callee to return some MacroRef. - pub fn get_macro_use_data(&self, span: Span) -> Option { + /// + /// FIXME: [`DumpVisitor::process_macro_use`] should actually dump this data + #[allow(dead_code)] + fn get_macro_use_data(&self, span: Span) -> Option { if !generated_code(span) { return None; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/sig.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/sig.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_save_analysis/src/sig.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_save_analysis/src/sig.rs 2021-06-17 03:53:50.000000000 +0000 @@ -614,11 +614,12 @@ start: offset + text.len(), end: offset + text.len() + param_text.as_str().len(), }); - if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind { + if let hir::GenericParamKind::Const { ref ty, default } = param.kind { param_text.push_str(": "); param_text.push_str(&ty_to_string(&ty)); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): push the `default` value here + if let Some(default) = default { + param_text.push_str(" = "); + param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id)); } } if !param.bounds.is_empty() { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/json.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/json.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/json.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/json.rs 2021-06-17 03:53:50.000000000 +0000 @@ -553,6 +553,12 @@ fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult where @@ -879,6 +885,12 @@ fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult where @@ -2354,6 +2366,13 @@ expect!(self.pop(), String).map(Cow::Owned) } + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error> { + for c in s.iter_mut() { + *c = self.read_u8()?; + } + Ok(()) + } + fn read_enum(&mut self, _name: &str, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/lib.rs 2021-06-17 03:53:50.000000000 +0000 @@ -16,7 +16,8 @@ #![feature(min_specialization)] #![feature(vec_spare_capacity)] #![feature(core_intrinsics)] -#![feature(int_bits_const)] +#![feature(maybe_uninit_array_assume_init)] +#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_slice)] #![feature(new_uninit)] #![cfg_attr(test, feature(test))] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/opaque.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/opaque.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/opaque.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/opaque.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,6 +1,7 @@ use crate::leb128::{self, max_leb128_len}; -use crate::serialize; +use crate::serialize::{self, Encoder as _}; use std::borrow::Cow; +use std::convert::TryInto; use std::fs::File; use std::io::{self, Write}; use std::mem::MaybeUninit; @@ -30,11 +31,6 @@ pub fn position(&self) -> usize { self.data.len() } - - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) { - self.data.extend_from_slice(s); - } } macro_rules! write_leb128 { @@ -154,7 +150,12 @@ #[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()) + } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult { + self.data.extend_from_slice(s); Ok(()) } } @@ -208,11 +209,6 @@ self.flushed + self.buffered } - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { - self.write_all(s) - } - pub fn flush(&mut self) -> FileEncodeResult { // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever // offers a raw buffer access API, we can use it, and remove this. @@ -508,6 +504,11 @@ self.emit_usize(v.len())?; self.emit_raw_bytes(v.as_bytes()) } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { + self.write_all(s) + } } // ----------------------------------------------------------------------------- @@ -541,23 +542,10 @@ } #[inline] - pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit]) -> Result<(), String> { + pub fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] { let start = self.position; - let end = start + s.len(); - assert!(end <= self.data.len()); - - // SAFETY: Both `src` and `dst` point to at least `s.len()` elements: - // `src` points to at least `s.len()` elements by above assert, and - // `dst` points to `s.len()` elements by derivation from `s`. - unsafe { - let src = self.data.as_ptr().add(start); - let dst = s.as_mut_ptr() as *mut u8; - ptr::copy_nonoverlapping(src, dst, s.len()); - } - - self.position = end; - - Ok(()) + self.position += bytes; + &self.data[start..self.position] } } @@ -677,6 +665,14 @@ fn error(&mut self, err: &str) -> Self::Error { err.to_string() } + + #[inline] + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), String> { + let start = self.position; + self.position += s.len(); + s.copy_from_slice(&self.data[start..self.position]); + Ok(()) + } } // Specializations for contiguous byte sequences follow. The default implementations for slices @@ -689,8 +685,7 @@ impl serialize::Encodable for [u8] { fn encode(&self, e: &mut Encoder) -> EncodeResult { serialize::Encoder::emit_usize(e, self.len())?; - e.emit_raw_bytes(self); - Ok(()) + e.emit_raw_bytes(self) } } @@ -706,15 +701,48 @@ impl<'a> serialize::Decodable> for Vec { fn decode(d: &mut Decoder<'a>) -> Result { let len = serialize::Decoder::read_usize(d)?; + Ok(d.read_raw_bytes(len).to_owned()) + } +} - let mut v = Vec::with_capacity(len); - let buf = &mut v.spare_capacity_mut()[..len]; - d.read_raw_bytes(buf)?; +// An integer that will always encode to 8 bytes. +pub struct IntEncodedWithFixedSize(pub u64); - unsafe { - v.set_len(len); - } +impl IntEncodedWithFixedSize { + pub const ENCODED_SIZE: usize = 8; +} + +impl serialize::Encodable for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut Encoder) -> EncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl serialize::Encodable for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl<'a> serialize::Decodable> for IntEncodedWithFixedSize { + #[inline] + fn decode(decoder: &mut Decoder<'a>) -> Result { + let _start_pos = decoder.position(); + let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE); + let _end_pos = decoder.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(v) + let value = u64::from_le_bytes(bytes.try_into().unwrap()); + Ok(IntEncodedWithFixedSize(value)) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/serialize.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/serialize.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/src/serialize.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/src/serialize.rs 2021-06-17 03:53:50.000000000 +0000 @@ -33,6 +33,7 @@ fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>; // Compound types: #[inline] @@ -224,6 +225,7 @@ fn read_f32(&mut self) -> Result; fn read_char(&mut self) -> Result; fn read_str(&mut self) -> Result, Self::Error>; + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error>; // Compound types: #[inline] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/tests/leb128.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/tests/leb128.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_serialize/tests/leb128.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_serialize/tests/leb128.rs 2021-06-17 03:53:50.000000000 +0000 @@ -1,4 +1,3 @@ -#![feature(int_bits_const)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/config.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/config.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/config.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/config.rs 2021-06-17 03:53:50.000000000 +0000 @@ -10,7 +10,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::impl_stable_hash_via_hash; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_target::abi::{Align, TargetDataLayout}; use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; @@ -19,7 +18,7 @@ use crate::parse::CrateConfig; use rustc_feature::UnstableFeatures; -use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST}; +use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::{FileName, FilePathMapping}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::SourceFileHashAlgorithm; @@ -36,66 +35,6 @@ use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; -bitflags! { - #[derive(Default, Encodable, Decodable)] - pub struct SanitizerSet: u8 { - const ADDRESS = 1 << 0; - const LEAK = 1 << 1; - const MEMORY = 1 << 2; - const THREAD = 1 << 3; - const HWADDRESS = 1 << 4; - } -} - -/// Formats a sanitizer set as a comma separated list of sanitizers' names. -impl fmt::Display for SanitizerSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut first = true; - for s in *self { - let name = match s { - SanitizerSet::ADDRESS => "address", - SanitizerSet::LEAK => "leak", - SanitizerSet::MEMORY => "memory", - SanitizerSet::THREAD => "thread", - SanitizerSet::HWADDRESS => "hwaddress", - _ => panic!("unrecognized sanitizer {:?}", s), - }; - if !first { - f.write_str(",")?; - } - f.write_str(name)?; - first = false; - } - Ok(()) - } -} - -impl IntoIterator for SanitizerSet { - type Item = SanitizerSet; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - [ - SanitizerSet::ADDRESS, - SanitizerSet::LEAK, - SanitizerSet::MEMORY, - SanitizerSet::THREAD, - SanitizerSet::HWADDRESS, - ] - .iter() - .copied() - .filter(|&s| self.contains(s)) - .collect::>() - .into_iter() - } -} - -impl HashStable for SanitizerSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.bits().hash_stable(ctx, hasher); - } -} - /// The different settings that the `-Z strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { @@ -136,19 +75,21 @@ /// This is what the `LtoCli` values get mapped to after resolving defaults and /// and taking other command line options into account. +/// +/// Note that linker plugin-based LTO is a different mechanism entirely. #[derive(Clone, PartialEq)] pub enum Lto { - /// Don't do any LTO whatsoever + /// Don't do any LTO whatsoever. No, - /// Do a full crate graph LTO with ThinLTO + /// Do a full-crate-graph (inter-crate) LTO with ThinLTO. Thin, - /// Do a local graph LTO with ThinLTO (only relevant for multiple codegen - /// units). + /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is + /// only relevant if multiple CGUs are used. ThinLocal, - /// Do a full crate graph LTO with "fat" LTO + /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO. Fat, } @@ -184,7 +125,38 @@ Block, } -#[derive(Clone, PartialEq, Hash)] +/// The different settings that the `-Z instrument-coverage` flag can have. +/// +/// Coverage instrumentation now supports combining `-Z instrument-coverage` +/// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1` +/// and higher). Nevertheless, there are many variables, depending on options +/// selected, code structure, and enabled attributes. If errors are encountered, +/// either while compiling or when generating `llvm-cov show` reports, consider +/// lowering the optimization level, including or excluding `-C link-dead-code`, +/// or using `-Z instrument-coverage=except-unused-functions` or `-Z +/// instrument-coverage=except-unused-generics`. +/// +/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the +/// coverage map, it will not attempt to generate synthetic functions for unused +/// (and not code-generated) functions (whether they are generic or not). As a +/// result, non-codegenned functions will not be included in the coverage map, +/// and will not appear, as covered or uncovered, in coverage reports. +/// +/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map, +/// unless the function has type parameters. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum InstrumentCoverage { + /// Default `-Z instrument-coverage` or `-Z instrument-coverage=statement` + All, + /// `-Z instrument-coverage=except-unused-generics` + ExceptUnusedGenerics, + /// `-Z instrument-coverage=except-unused-functions` + ExceptUnusedFunctions, + /// `-Z instrument-coverage=off` (or `no`, etc.) + Off, +} + +#[derive(Clone, PartialEq, Hash, Debug)] pub enum LinkerPluginLto { LinkerPlugin(PathBuf), LinkerPluginAuto, @@ -200,7 +172,7 @@ } } -#[derive(Clone, PartialEq, Hash)] +#[derive(Clone, PartialEq, Hash, Debug)] pub enum SwitchWithOptPath { Enabled(Option), Disabled, @@ -474,6 +446,7 @@ } impl Externs { + /// Used for testing. pub fn new(data: BTreeMap) -> Externs { Externs(data) } @@ -485,6 +458,10 @@ pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> { self.0.iter() } + + pub fn len(&self) -> usize { + self.0.len() + } } impl ExternEntry { @@ -573,13 +550,6 @@ } } - pub fn get_input(&mut self) -> Option<&mut String> { - match *self { - Input::File(_) => None, - Input::Str { ref mut input, .. } => Some(input), - } - } - pub fn source_name(&self) -> FileName { match *self { Input::File(ref ifile) => ifile.clone().into(), @@ -732,8 +702,10 @@ cli_forced_codegen_units: None, cli_forced_thinlto_off: false, remap_path_prefix: Vec::new(), + real_rust_source_base_dir: None, edition: DEFAULT_EDITION, json_artifact_notifications: false, + json_unused_externs: false, pretty: None, } } @@ -747,12 +719,6 @@ || self.debugging_opts.query_dep_graph } - #[inline(always)] - pub fn enable_dep_node_debug_strs(&self) -> bool { - cfg!(debug_assertions) - && (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) - } - pub fn file_path_mapping(&self) -> FilePathMapping { FilePathMapping::new(self.remap_path_prefix.clone()) } @@ -813,7 +779,7 @@ impl_stable_hash_via_hash!(CrateType); -#[derive(Clone, Hash)] +#[derive(Clone, Hash, Debug, PartialEq, Eq)] pub enum Passes { Some(Vec), All, @@ -832,7 +798,7 @@ CrateType::Rlib } -pub fn default_configuration(sess: &Session) -> CrateConfig { +fn default_configuration(sess: &Session) -> CrateConfig { let end = &sess.target.endian; let arch = &sess.target.arch; let wordsz = sess.target.pointer_width.to_string(); @@ -927,14 +893,14 @@ user_cfg } -pub fn build_target_config(opts: &Options, target_override: Option) -> Target { +pub(super) fn build_target_config(opts: &Options, target_override: Option) -> Target { let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok); let target = target_result.unwrap_or_else(|e| { early_error( opts.error_format, &format!( "Error loading target specification: {}. \ - Use `--print target-list` for a list of built-in targets", + Run `rustc --print target-list` for a list of built-in targets", e ), ) @@ -1029,9 +995,6 @@ pub fn flag_s(a: S, b: S, c: S) -> R { stable(longer(a, b), move |opts| opts.optflag(a, b, c)) } - pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) - } pub fn flagmulti_s(a: S, b: S, c: S) -> R { stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) } @@ -1042,15 +1005,6 @@ pub fn multi(a: S, b: S, c: S, d: S) -> R { unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } - pub fn flag(a: S, b: S, c: S) -> R { - unstable(longer(a, b), move |opts| opts.optflag(a, b, c)) - } - pub fn flagopt(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) - } - pub fn flagmulti(a: S, b: S, c: S) -> R { - unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) - } } /// Returns the "short" subset of the rustc command line options, @@ -1250,15 +1204,23 @@ } } +/// Possible json config files +pub struct JsonConfig { + pub json_rendered: HumanReadableErrorType, + pub json_artifact_notifications: bool, + pub json_unused_externs: bool, +} + /// Parse the `--json` flag. /// /// The first value returned is how to render JSON diagnostics, and the second /// is whether or not artifact notifications are enabled. -pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) { +pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = HumanReadableErrorType::Default; let mut json_color = ColorConfig::Never; let mut json_artifact_notifications = false; + let mut json_unused_externs = 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 @@ -1275,6 +1237,7 @@ "diagnostic-short" => json_rendered = HumanReadableErrorType::Short, "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, "artifacts" => json_artifact_notifications = true, + "unused-externs" => json_unused_externs = true, s => early_error( ErrorOutputType::default(), &format!("unknown `--json` option `{}`", s), @@ -1282,7 +1245,12 @@ } } } - (json_rendered(json_color), json_artifact_notifications) + + JsonConfig { + json_rendered: json_rendered(json_color), + json_artifact_notifications, + json_unused_externs, + } } /// Parses the `--error-format` flag. @@ -1355,13 +1323,16 @@ }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { - early_error( - ErrorOutputType::default(), - &format!( - "edition {} is unstable and only available with -Z unstable-options.", - edition, - ), - ) + let is_nightly = nightly_options::match_is_nightly_build(matches); + let msg = if !is_nightly { + format!( + "the crate requires edition {}, but the latest edition supported by this Rust version is {}", + edition, LATEST_STABLE_EDITION + ) + } else { + format!("edition {} is unstable and only available with -Z unstable-options", edition) + }; + early_error(ErrorOutputType::default(), &msg) } edition @@ -1860,7 +1831,8 @@ let edition = parse_crate_edition(matches); - let (json_rendered, json_artifact_notifications) = parse_json(matches); + let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } = + parse_json(matches); let error_format = parse_error_format(matches, color, json_rendered); @@ -1873,6 +1845,14 @@ let mut debugging_opts = build_debugging_options(matches, error_format); check_debug_option_stability(&debugging_opts, error_format, json_rendered); + if !debugging_opts.unstable_options && json_unused_externs { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to enable \ + the flag `--json=unused-externs`", + ); + } + let output_types = parse_output_types(&debugging_opts, matches, error_format); let mut cg = build_codegen_options(matches, error_format); @@ -1916,7 +1896,9 @@ ); } - if debugging_opts.instrument_coverage { + if debugging_opts.instrument_coverage.is_some() + && debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off) + { if cg.profile_generate.enabled() || cg.profile_use.is_some() { early_error( error_format, @@ -2004,6 +1986,34 @@ } } + // Try to find a directory containing the Rust `src`, for more details see + // the doc comment on the `real_rust_source_base_dir` field. + let tmp_buf; + let sysroot = match &sysroot_opt { + Some(s) => s, + None => { + tmp_buf = crate::filesearch::get_or_default_sysroot(); + &tmp_buf + } + }; + let real_rust_source_base_dir = { + // This is the location used by the `rust-src` `rustup` component. + let mut candidate = sysroot.join("lib/rustlib/src/rust"); + if let Ok(metadata) = candidate.symlink_metadata() { + // Replace the symlink rustbuild creates, with its destination. + // We could try to use `fs::canonicalize` instead, but that might + // produce unnecessarily verbose path. + if metadata.file_type().is_symlink() { + if let Ok(symlink_dest) = std::fs::read_link(&candidate) { + candidate = symlink_dest; + } + } + } + + // Only use this directory if it has a file we can expect to always find. + if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } + }; + Options { crate_types, optimize: opt_level, @@ -2034,8 +2044,10 @@ cli_forced_codegen_units: codegen_units, cli_forced_thinlto_off: disable_thinlto, remap_path_prefix, + real_rust_source_base_dir, edition, json_artifact_notifications, + json_unused_externs, pretty, } } @@ -2279,7 +2291,7 @@ pub fn needs_analysis(&self) -> bool { use PpMode::*; - matches!(*self, Mir | MirCFG) + matches!(*self, Mir | MirCFG | ThirTree) } } @@ -2303,8 +2315,8 @@ /// how the hash should be calculated when adding a new command-line argument. crate mod dep_tracking { use super::{ - CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel, - OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath, + CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto, + LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; @@ -2313,7 +2325,7 @@ use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; + use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel}; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2357,6 +2369,7 @@ impl_dep_tracking_hash_via_hash!(PathBuf); impl_dep_tracking_hash_via_hash!(lint::Level); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); @@ -2369,6 +2382,7 @@ impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(CrateType); @@ -2395,6 +2409,7 @@ impl_dep_tracking_hash_for_sortable_vec_of!(String); impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); + impl_dep_tracking_hash_for_sortable_vec_of!((PathBuf, PathBuf)); impl_dep_tracking_hash_for_sortable_vec_of!(CrateType); impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option, NativeLibKind)); @@ -2430,7 +2445,7 @@ } // This is a stable hash because BTreeMap is a sorted container - pub fn stable_hash( + crate fn stable_hash( sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, hasher: &mut DefaultHasher, error_format: ErrorOutputType, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,11 +1,9 @@ #![feature(crate_visibility_modifier)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] -extern crate bitflags; -#[macro_use] extern crate rustc_macros; pub mod cgu_reuse_tracker; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/options.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/options.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/options.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/options.rs 2021-06-17 03:53:51.000000000 +0000 @@ -5,7 +5,7 @@ use crate::search_paths::SearchPath; use crate::utils::NativeLibKind; -use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; +use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; use rustc_feature::UnstableFeatures; @@ -20,73 +20,112 @@ use std::path::PathBuf; use std::str; -macro_rules! hash_option { - ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => {{}}; - ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => {{ +macro_rules! insert { + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => { if $sub_hashes .insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash) .is_some() { panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) } + }; +} + +macro_rules! hash_opt { + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [UNTRACKED]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [TRACKED]) => {{ insert!($opt_name, $opt_expr, $sub_hashes) }}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $for_crate_hash: ident, [TRACKED_NO_CRATE_HASH]) => {{ + if !$for_crate_hash { + insert!($opt_name, $opt_expr, $sub_hashes) + } }}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [SUBSTRUCT]) => {{}}; +} + +macro_rules! hash_substruct { + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [UNTRACKED]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => { + use crate::config::dep_tracking::DepTrackingHash; + $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format); + }; } macro_rules! top_level_options { - (pub struct Options { $( - $opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*], + ( $( #[$top_level_attr:meta] )* pub struct Options { $( + $( #[$attr:meta] )* + $opt:ident : $t:ty [$dep_tracking_marker:ident], )* } ) => ( #[derive(Clone)] + $( #[$top_level_attr] )* pub struct Options { - $(pub $opt: $t),* + $( + $( #[$attr] )* + pub $opt: $t + ),* } impl Options { - pub fn dep_tracking_hash(&self) -> u64 { + pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> u64 { let mut sub_hashes = BTreeMap::new(); $({ - hash_option!($opt, - &self.$opt, - &mut sub_hashes, - [$dep_tracking_marker $($warn_val, - $warn_text, - self.error_format)*]); + hash_opt!($opt, + &self.$opt, + &mut sub_hashes, + for_crate_hash, + [$dep_tracking_marker]); })* let mut hasher = DefaultHasher::new(); dep_tracking::stable_hash(sub_hashes, &mut hasher, self.error_format); + $({ + hash_substruct!($opt, + &self.$opt, + self.error_format, + for_crate_hash, + &mut hasher, + [$dep_tracking_marker]); + })* hasher.finish() } } ); } -// The top-level command-line options struct. -// -// For each option, one has to specify how it behaves with regard to the -// dependency tracking system of incremental compilation. This is done via the -// square-bracketed directive after the field type. The options are: -// -// [TRACKED] -// A change in the given field will cause the compiler to completely clear the -// incremental compilation cache before proceeding. -// -// [UNTRACKED] -// Incremental compilation is not influenced by this option. -// -// If you add a new option to this struct or one of the sub-structs like -// `CodegenOptions`, think about how it influences incremental compilation. If in -// doubt, specify [TRACKED], which is always "correct" but might lead to -// unnecessary re-compilation. top_level_options!( + /// The top-level command-line options struct. + /// + /// For each option, one has to specify how it behaves with regard to the + /// dependency tracking system of incremental compilation. This is done via the + /// square-bracketed directive after the field type. The options are: + /// + /// - `[TRACKED]` + /// A change in the given field will cause the compiler to completely clear the + /// incremental compilation cache before proceeding. + /// + /// - `[TRACKED_NO_CRATE_HASH]` + /// Same as `[TRACKED]`, but will not affect the crate hash. This is useful for options that only + /// affect the incremental cache. + /// + /// - `[UNTRACKED]` + /// Incremental compilation is not influenced by this option. + /// + /// - `[SUBSTRUCT]` + /// Second-level sub-structs containing more options. + /// + /// If you add a new option to this struct or one of the sub-structs like + /// `CodegenOptions`, think about how it influences incremental compilation. If in + /// doubt, specify `[TRACKED]`, which is always "correct" but might lead to + /// unnecessary re-compilation. pub struct Options { - // The crate config requested for the session, which may be combined - // with additional crate configurations during the compile process. + /// The crate config requested for the session, which may be combined + /// with additional crate configurations during the compile process. crate_types: Vec [TRACKED], optimize: OptLevel [TRACKED], - // Include the `debug_assertions` flag in dependency tracking, since it - // can influence whether overflow checks are done or not. + /// Include the `debug_assertions` flag in dependency tracking, since it + /// can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED], @@ -102,51 +141,62 @@ test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - // If `Some`, enable incremental compilation, using the given - // directory to store intermediate results. + /// If `Some`, enable incremental compilation, using the given + /// directory to store intermediate results. incremental: Option [UNTRACKED], - debugging_opts: DebuggingOptions [TRACKED], + debugging_opts: DebuggingOptions [SUBSTRUCT], prints: Vec [UNTRACKED], - // Determines which borrow checker(s) to run. This is the parsed, sanitized - // version of `debugging_opts.borrowck`, which is just a plain string. + /// Determines which borrow checker(s) to run. This is the parsed, sanitized + /// version of `debugging_opts.borrowck`, which is just a plain string. borrowck_mode: BorrowckMode [UNTRACKED], - cg: CodegenOptions [TRACKED], + cg: CodegenOptions [SUBSTRUCT], externs: Externs [UNTRACKED], extern_dep_specs: ExternDepSpecs [UNTRACKED], crate_name: Option [TRACKED], - // An optional name to use as the crate for std during std injection, - // written `extern crate name as std`. Defaults to `std`. Used by - // out-of-tree drivers. + /// An optional name to use as the crate for std during std injection, + /// written `extern crate name as std`. Defaults to `std`. Used by + /// out-of-tree drivers. alt_std_name: Option [TRACKED], - // Indicates how the compiler should treat unstable features. + /// Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], - // Indicates whether this run of the compiler is actually rustdoc. This - // is currently just a hack and will be removed eventually, so please - // try to not rely on this too much. + /// Indicates whether this run of the compiler is actually rustdoc. This + /// is currently just a hack and will be removed eventually, so please + /// try to not rely on this too much. actually_rustdoc: bool [TRACKED], - // Control path trimming. + /// Control path trimming. trimmed_def_paths: TrimmedDefPaths [TRACKED], - // Specifications of codegen units / ThinLTO which are forced as a - // result of parsing command line options. These are not necessarily - // what rustc was invoked with, but massaged a bit to agree with - // commands like `--emit llvm-ir` which they're often incompatible with - // if we otherwise use the defaults of rustc. + /// Specifications of codegen units / ThinLTO which are forced as a + /// result of parsing command line options. These are not necessarily + /// what rustc was invoked with, but massaged a bit to agree with + /// commands like `--emit llvm-ir` which they're often incompatible with + /// if we otherwise use the defaults of rustc. cli_forced_codegen_units: Option [UNTRACKED], cli_forced_thinlto_off: bool [UNTRACKED], - // Remap source path prefixes in all output (messages, object files, debug, etc.). - remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], + /// Remap source path prefixes in all output (messages, object files, debug, etc.). + remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH], + /// Base directory containing the `src/` for the Rust standard library, and + /// potentially `rustc` as well, if we can can find it. Right now it's always + /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component). + /// + /// This directory is what the virtual `/rustc/$hash` is translated back to, + /// if Rust was built with path remapping to `/rustc/$hash` enabled + /// (the `rust.remap-debuginfo` option in `config.toml`). + real_rust_source_base_dir: Option [TRACKED_NO_CRATE_HASH], edition: Edition [TRACKED], - // `true` if we're emitting JSON blobs about each artifact produced - // by the compiler. + /// `true` if we're emitting JSON blobs about each artifact produced + /// by the compiler. json_artifact_notifications: bool [TRACKED], + /// `true` if we're emitting a JSON blob containing the unused externs + json_unused_externs: bool [UNTRACKED], + pretty: Option [UNTRACKED], } ); @@ -163,10 +213,10 @@ ($struct_name:ident, $setter_name:ident, $defaultfn:ident, $buildfn:ident, $prefix:expr, $outputname:expr, $stat:ident, $mod_desc:ident, $mod_set:ident, - $($opt:ident : $t:ty = ( + $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, - [$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*], + [$dep_tracking_marker:ident], $desc:expr) ),* ,) => ( @@ -174,7 +224,7 @@ pub struct $struct_name { $(pub $opt: $t),* } pub fn $defaultfn() -> $struct_name { - $struct_name { $($opt: $init),* } + $struct_name { $( $( #[$attr] )* $opt: $init),* } } pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name @@ -216,18 +266,21 @@ return op; } - impl dep_tracking::DepTrackingHash for $struct_name { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + impl $struct_name { + fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { let mut sub_hashes = BTreeMap::new(); $({ - hash_option!($opt, - &self.$opt, - &mut sub_hashes, - [$dep_tracking_marker $($dep_warn_val, - $dep_warn_text, - error_format)*]); + hash_opt!($opt, + &self.$opt, + &mut sub_hashes, + _for_crate_hash, + [$dep_tracking_marker]); })* - dep_tracking::stable_hash(sub_hashes, hasher, error_format); + let mut hasher = DefaultHasher::new(); + dep_tracking::stable_hash(sub_hashes, + &mut hasher, + error_format); + hasher.finish() } } @@ -248,9 +301,9 @@ pub const parse_list: &str = "a space-separated list of strings"; pub const parse_opt_list: &str = parse_list; pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; - pub const parse_uint: &str = "a number"; - pub const parse_opt_uint: &str = parse_uint; - pub const parse_threads: &str = parse_uint; + pub const parse_number: &str = "a number"; + pub const parse_opt_number: &str = parse_number; + pub const parse_threads: &str = parse_number; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; @@ -262,6 +315,7 @@ pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; + pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; pub const parse_lto: &str = @@ -413,16 +467,16 @@ } } - /// Use this for any uint option that has a static default. - fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool { + /// Use this for any numeric option that has a static default. + fn parse_number(slot: &mut T, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(i) => { *slot = i; true }, None => false } } - /// Use this for any uint option that lacks a static default. - fn parse_opt_uint(slot: &mut Option, v: Option<&str>) -> bool { + /// Use this for any numeric option that lacks a static default. + fn parse_opt_number(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } None => false @@ -592,6 +646,41 @@ true } + fn parse_instrument_coverage(slot: &mut Option, v: Option<&str>) -> bool { + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + Some(InstrumentCoverage::All) + } else { + None + }; + return true + } + } + + let v = match v { + None => { + *slot = Some(InstrumentCoverage::All); + return true; + } + Some(v) => v, + }; + + *slot = Some(match v { + "all" => InstrumentCoverage::All, + "except-unused-generics" | "except_unused_generics" => { + InstrumentCoverage::ExceptUnusedGenerics + } + "except-unused-functions" | "except_unused_functions" => { + InstrumentCoverage::ExceptUnusedFunctions + } + "off" | "no" | "n" | "false" | "0" => InstrumentCoverage::Off, + _ => return false, + }); + true + } + fn parse_treat_err_as_bug(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } @@ -748,13 +837,13 @@ "this option is deprecated and does nothing"), code_model: Option = (None, parse_code_model, [TRACKED], "choose the code model to use (`rustc --print code-models` for details)"), - codegen_units: Option = (None, parse_opt_uint, [UNTRACKED], + codegen_units: Option = (None, parse_opt_number, [UNTRACKED], "divide crate into N units to optimize in parallel"), control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), - debuginfo: usize = (0, parse_uint, [TRACKED], + debuginfo: usize = (0, parse_number, [TRACKED], "debug info emission level (0 = no debug info, 1 = line tables only, \ 2 = full debug info with variable and type information; default: 0)"), default_linker_libraries: bool = (false, parse_bool, [UNTRACKED], @@ -769,13 +858,13 @@ "force use of unwind tables"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), - inline_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_threshold: Option = (None, parse_opt_number, [TRACKED], "set the threshold for inlining a function"), link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], "extra arguments to append to the linker invocation (space separated)"), - link_dead_code: Option = (None, parse_opt_bool, [UNTRACKED], + link_dead_code: Option = (None, parse_opt_bool, [TRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), link_self_contained: Option = (None, parse_opt_bool, [UNTRACKED], "control whether to link Rust provided C objects/libraries or rely @@ -870,8 +959,6 @@ (default: no)"), borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED], "select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"), - borrowck_stats: bool = (false, parse_bool, [UNTRACKED], - "gather borrowck statistics (default: no)"), cgu_partitioning_strategy: Option = (None, parse_opt_string, [TRACKED], "the codegen unit partitioning strategy to use"), chalk: bool = (false, parse_bool, [TRACKED], @@ -959,20 +1046,22 @@ "verify incr. comp. hashes of green query instances (default: no)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED], "enable MIR inlining (default: no)"), - inline_mir_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_mir_threshold: Option = (None, parse_opt_number, [TRACKED], "a default MIR inlining threshold (default: 50)"), - inline_mir_hint_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_mir_hint_threshold: Option = (None, parse_opt_number, [TRACKED], "inlining threshold for functions with inline hint (default: 100)"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], "control whether `#[inline]` functions are in all CGUs"), input_stats: bool = (false, parse_bool, [UNTRACKED], "gather statistics about the input (default: no)"), - instrument_coverage: bool = (false, parse_bool, [TRACKED], + 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`, \ and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \ implies `-Z symbol-mangling-version=v0`; disables/overrides some Rust \ - optimizations (default: no)"), + optimizations. Optional values are: `=all` (default coverage), \ + `=except-unused-generics`, `=except-unused-functions`, or `=off` \ + (default: instrument-coverage=off)"), instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -995,10 +1084,10 @@ mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), - mir_opt_level: Option = (None, parse_opt_uint, [TRACKED], + mir_opt_level: Option = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), - mutable_noalias: bool = (false, parse_bool, [TRACKED], - "emit noalias metadata for mutable references (default: no)"), + mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], + "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"), new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED], "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], @@ -1089,7 +1178,7 @@ self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], "run the self profiler and output the raw event data"), - // keep this in sync with the event filter names in librustc_data_structures/profiling.rs + /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs self_profile_events: Option> = (None, parse_opt_comma_list, [UNTRACKED], "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` @@ -1101,7 +1190,7 @@ "show spans for compiler debugging (expr|pat|ty)"), span_debug: bool = (false, parse_bool, [UNTRACKED], "forward proc_macro::Span's `Debug` impl to `Span`"), - // o/w tests have closure@path + /// o/w tests have closure@path span_free_formats: bool = (false, parse_bool, [UNTRACKED], "exclude spans when debug-printing compiler state (default: no)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], @@ -1116,16 +1205,16 @@ "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help (default: no)"), - terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], + terminal_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current terminal width"), tune_cpu: Option = (None, parse_opt_string, [TRACKED], "select processor to schedule for (`rustc --print target-cpus` for details)"), thinlto: Option = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), - // We default to 1 here since we want to behave like - // a sequential compiler for now. This'll likely be adjusted - // in the future. Note that -Zthreads=0 is the way to get - // the num_cpus behavior. + /// We default to 1 here since we want to behave like + /// a sequential compiler for now. This'll likely be adjusted + /// in the future. Note that -Zthreads=0 is the way to get + /// the num_cpus behavior. threads: usize = (1, parse_threads, [UNTRACKED], "use a thread pool with N threads"), time: bool = (false, parse_bool, [UNTRACKED], @@ -1181,7 +1270,7 @@ // - compiler/rustc_interface/src/tests.rs } -#[derive(Clone, Hash)] +#[derive(Clone, Hash, PartialEq, Eq, Debug)] pub enum WasiExecModel { Command, Reactor, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/parse.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/parse.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/parse.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/parse.rs 2021-06-17 03:53:51.000000000 +0000 @@ -140,6 +140,7 @@ } impl ParseSess { + /// Used for testing. pub fn new(file_path_mapping: FilePathMapping) -> Self { let sm = Lrc::new(SourceMap::new(file_path_mapping)); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone())); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/session.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/session.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/session.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/session.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,7 +1,7 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; -use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath}; +use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath}; use crate::filesearch; use crate::lint::{self, LintId}; use crate::parse::ParseSess; @@ -20,7 +20,7 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; +use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_lint_defs::FutureBreakage; pub use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::edition::Edition; @@ -28,7 +28,7 @@ use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; -use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel}; +use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel}; use std::cell::{self, RefCell}; use std::env; @@ -83,6 +83,12 @@ } } +impl From for Limit { + fn from(value: usize) -> Self { + Self::new(value) + } +} + impl fmt::Display for Limit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) @@ -143,6 +149,10 @@ /// operations such as auto-dereference and monomorphization. pub recursion_limit: OnceCell, + /// The size at which the `large_assignments` lint starts + /// being emitted. + pub move_size_limit: OnceCell, + /// The maximum length of types during monomorphization. pub type_length_limit: OnceCell, @@ -204,15 +214,6 @@ /// drown everything else in noise. miri_unleashed_features: Lock)>>, - /// Base directory containing the `src/` for the Rust standard library, and - /// potentially `rustc` as well, if we can can find it. Right now it's always - /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component). - /// - /// This directory is what the virtual `/rustc/$hash` is translated back to, - /// if Rust was built with path remapping to `/rustc/$hash` enabled - /// (the `rust.remap-debuginfo` option in `config.toml`). - pub real_rust_source_base_dir: Option, - /// Architecture to use for interpreting asm!. pub asm_arch: Option, @@ -241,8 +242,7 @@ enum DiagnosticBuilderMethod { Note, SpanNote, - SpanSuggestion(String), // suggestion - // Add more variants as needed to support one-time diagnostics. + // Add more variants as needed to support one-time diagnostics. } /// Trait implemented by error types. This should not be implemented manually. Instead, use @@ -354,6 +354,11 @@ } #[inline] + pub fn move_size_limit(&self) -> usize { + self.move_size_limit.get().copied().unwrap() + } + + #[inline] pub fn type_length_limit(&self) -> Limit { self.type_length_limit.get().copied().unwrap() } @@ -551,15 +556,6 @@ let span = span_maybe.expect("`span_note` needs a span"); diag_builder.span_note(span, message); } - DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { - let span = span_maybe.expect("`span_suggestion_*` needs a span"); - diag_builder.span_suggestion( - span, - message, - suggestion, - Applicability::Unspecified, - ); - } } } } @@ -589,23 +585,6 @@ self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None); } - pub fn diag_span_suggestion_once<'a, 'b>( - &'a self, - diag_builder: &'b mut DiagnosticBuilder<'a>, - msg_id: DiagnosticMessageId, - span: Span, - message: &str, - suggestion: String, - ) { - self.diag_once( - diag_builder, - DiagnosticBuilderMethod::SpanSuggestion(suggestion), - msg_id, - message, - Some(span), - ); - } - #[inline] pub fn source_map(&self) -> &SourceMap { self.parse_sess.source_map() @@ -631,9 +610,6 @@ pub fn verify_llvm_ir(&self) -> bool { self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some() } - pub fn borrowck_stats(&self) -> bool { - self.opts.debugging_opts.borrowck_stats - } pub fn print_llvm_passes(&self) -> bool { self.opts.debugging_opts.print_llvm_passes } @@ -793,13 +769,6 @@ } } - pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect { - match self.asm_arch { - Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel, - _ => rustc_ast::LlvmAsmDialect::Att, - } - } - pub fn relocation_model(&self) -> RelocModel { self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model) } @@ -844,8 +813,11 @@ // This is used to control the emission of the `uwtable` attribute on // LLVM functions. // - // At the very least, unwind tables are needed when compiling with - // `-C panic=unwind`. + // Unwind tables are needed when compiling with `-C panic=unwind`, but + // LLVM won't omit unwind tables unless the function is also marked as + // `nounwind`, so users are allowed to disable `uwtable` emission. + // Historically rustc always emits `uwtable` attributes by default, so + // even they can be disabled, they're still emitted by default. // // On some targets (including windows), however, exceptions include // other events such as illegal instructions, segfaults, etc. This means @@ -858,13 +830,10 @@ // If a target requires unwind tables, then they must be emitted. // Otherwise, we can defer to the `-C force-unwind-tables=` // value, if it is provided, or disable them, if not. - if self.panic_strategy() == PanicStrategy::Unwind { - true - } else if self.target.requires_uwtable { - true - } else { - self.opts.cg.force_unwind_tables.unwrap_or(false) - } + self.target.requires_uwtable + || self.opts.cg.force_unwind_tables.unwrap_or( + self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable, + ) } /// Returns the symbol name for the registrar function, @@ -897,22 +866,6 @@ ) } - pub fn set_incr_session_load_dep_graph(&self, load: bool) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); - - if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session { - *load_dep_graph = load; - } - } - - pub fn incr_session_load_dep_graph(&self) -> bool { - let incr_comp_session = self.incr_comp_session.borrow(); - match *incr_comp_session { - IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph, - _ => false, - } - } - pub fn init_incr_comp_session( &self, session_dir: PathBuf, @@ -1150,6 +1103,21 @@ self.opts.cg.link_dead_code.unwrap_or(false) } + pub fn instrument_coverage(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + != config::InstrumentCoverage::Off + } + + pub fn instrument_coverage_except_unused_generics(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + == config::InstrumentCoverage::ExceptUnusedGenerics + } + + pub fn instrument_coverage_except_unused_functions(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + == config::InstrumentCoverage::ExceptUnusedFunctions + } + pub fn mark_attr_known(&self, attr: &Attribute) { self.known_attrs.lock().mark(attr) } @@ -1413,26 +1381,6 @@ _ => CtfeBacktrace::Disabled, }); - // Try to find a directory containing the Rust `src`, for more details see - // the doc comment on the `real_rust_source_base_dir` field. - let real_rust_source_base_dir = { - // This is the location used by the `rust-src` `rustup` component. - let mut candidate = sysroot.join("lib/rustlib/src/rust"); - if let Ok(metadata) = candidate.symlink_metadata() { - // Replace the symlink rustbuild creates, with its destination. - // We could try to use `fs::canonicalize` instead, but that might - // produce unnecessarily verbose path. - if metadata.file_type().is_symlink() { - if let Ok(symlink_dest) = std::fs::read_link(&candidate) { - candidate = symlink_dest; - } - } - } - - // Only use this directory if it has a file we can expect to always find. - if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } - }; - let asm_arch = if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None }; @@ -1452,6 +1400,7 @@ features: OnceCell::new(), lint_store: OnceCell::new(), recursion_limit: OnceCell::new(), + move_size_limit: OnceCell::new(), type_length_limit: OnceCell::new(), const_eval_limit: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), @@ -1475,7 +1424,6 @@ system_library_path: OneThread::new(RefCell::new(Default::default())), ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), - real_rust_source_base_dir, asm_arch, target_features: FxHashSet::default(), known_attrs: Lock::new(MarkedAttrs::new()), @@ -1521,13 +1469,6 @@ // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { - if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables { - sess.err( - "panic=unwind requires unwind tables, they cannot be disabled \ - with `-C force-unwind-tables=no`.", - ); - } - if sess.target.requires_uwtable && !include_uwtables { sess.err( "target requires unwind tables, they cannot be disabled with \ @@ -1555,59 +1496,22 @@ ); } - const ASAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-fuchsia", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-fuchsia", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - ]; - const LSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-linux-gnu", - ]; - const MSAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"]; - const TSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - ]; - const HWASAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-linux-android", "aarch64-unknown-linux-gnu"]; - - // Sanitizers can only be used on some tested platforms. - for s in sess.opts.debugging_opts.sanitizer { - let supported_targets = match s { - SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS, - SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS, - SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS, - SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS, - SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS, - _ => panic!("unrecognized sanitizer {}", s), - }; - if !supported_targets.contains(&&*sess.opts.target_triple.triple()) { - sess.err(&format!( - "`-Zsanitizer={}` only works with targets: {}", - s, - supported_targets.join(", ") - )); - } - let conflicting = sess.opts.debugging_opts.sanitizer - s; - if !conflicting.is_empty() { - sess.err(&format!( - "`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", - s, conflicting, - )); - // Don't report additional errors. - break; - } + // Sanitizers can only be used on platforms that we know have working sanitizer codegen. + let supported_sanitizers = sess.target.options.supported_sanitizers; + let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers; + match unsupported_sanitizers.into_iter().count() { + 0 => {} + 1 => sess + .err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)), + _ => sess.err(&format!( + "{} sanitizers are not supported for this target", + unsupported_sanitizers + )), + } + // Cannot mix and match sanitizers. + let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter(); + if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { + sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second)); } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/utils.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/utils.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_session/src/utils.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_session/src/utils.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,7 +1,13 @@ +use crate::parse::ParseSess; use crate::session::Session; +use rustc_ast::token::{self, DelimToken, Nonterminal, Token}; +use rustc_ast::tokenstream::CanSynthesizeMissingTokens; +use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_data_structures::profiling::VerboseTimingGuard; use std::path::{Path, PathBuf}; +pub type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream; + impl Session { pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> { self.prof.verbose_generic_activity(what) @@ -53,3 +59,52 @@ &self.original } } + +// FIXME: Find a better spot for this - it needs to be accessible from `rustc_ast_lowering`, +// and needs to access `ParseSess +pub struct FlattenNonterminals<'a> { + pub parse_sess: &'a ParseSess, + pub synthesize_tokens: CanSynthesizeMissingTokens, + pub nt_to_tokenstream: NtToTokenstream, +} + +impl<'a> FlattenNonterminals<'a> { + pub fn process_token_stream(&mut self, tokens: TokenStream) -> TokenStream { + fn can_skip(stream: &TokenStream) -> bool { + stream.trees().all(|tree| match tree { + TokenTree::Token(token) => !matches!(token.kind, token::Interpolated(_)), + TokenTree::Delimited(_, _, inner) => can_skip(&inner), + }) + } + + if can_skip(&tokens) { + return tokens; + } + + tokens.into_trees().flat_map(|tree| self.process_token_tree(tree).into_trees()).collect() + } + + pub fn process_token_tree(&mut self, tree: TokenTree) -> TokenStream { + match tree { + TokenTree::Token(token) => self.process_token(token), + TokenTree::Delimited(span, delim, tts) => { + TokenTree::Delimited(span, delim, self.process_token_stream(tts)).into() + } + } + } + + pub fn process_token(&mut self, token: Token) -> TokenStream { + match token.kind { + token::Interpolated(nt) => { + let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens); + TokenTree::Delimited( + DelimSpan::from_single(token.span), + DelimToken::NoDelim, + self.process_token_stream(tts), + ) + .into() + } + _ => TokenTree::Token(token).into(), + } + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/def_id.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/def_id.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/def_id.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/def_id.rs 2021-06-17 03:53:51.000000000 +0000 @@ -160,6 +160,8 @@ } /// Returns the crate-local part of the [DefPathHash]. + /// + /// Used for tests. #[inline] pub fn local_hash(&self) -> u64 { self.0.as_value().1 diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/hygiene.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/hygiene.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/hygiene.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/hygiene.rs 2021-06-17 03:53:51.000000000 +0000 @@ -413,7 +413,7 @@ let names: Vec<_> = range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect(); HygieneData::with(|data| { - range_to_update.zip(names.into_iter()).for_each(|(idx, name)| { + range_to_update.zip(names).for_each(|(idx, name)| { data.syntax_context_data[idx].dollar_crate_name = name; }) }) @@ -748,7 +748,7 @@ /// Used to force two `ExpnData`s to have different `Fingerprint`s. /// Due to macro expansion, it's possible to end up with two `ExpnId`s - /// that have identical `ExpnData`s. This violates the constract of `HashStable` + /// that have identical `ExpnData`s. This violates the contract of `HashStable` /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal /// (since the numerical `ExpnId` value is not considered by the `HashStable` /// implementation). @@ -1176,11 +1176,7 @@ Ok(new_ctxt) } -pub fn num_syntax_ctxts() -> usize { - HygieneData::with(|data| data.syntax_context_data.len()) -} - -pub fn for_all_ctxts_in Result<(), E>>( +fn for_all_ctxts_in Result<(), E>>( ctxts: impl Iterator, mut f: F, ) -> Result<(), E> { @@ -1193,7 +1189,7 @@ Ok(()) } -pub fn for_all_expns_in Result<(), E>>( +fn for_all_expns_in Result<(), E>>( expns: impl Iterator, mut f: F, ) -> Result<(), E> { @@ -1206,16 +1202,6 @@ Ok(()) } -pub fn for_all_data Result<(), E>>( - mut f: F, -) -> Result<(), E> { - let all_data = HygieneData::with(|data| data.syntax_context_data.clone()); - for (i, data) in all_data.into_iter().enumerate() { - f((i as u32, SyntaxContext(i as u32), &data))?; - } - Ok(()) -} - impl Encodable for ExpnId { default fn encode(&self, _: &mut E) -> Result<(), E::Error> { panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::()); @@ -1228,14 +1214,6 @@ } } -pub fn for_all_expn_data Result<(), E>>(mut f: F) -> Result<(), E> { - let all_data = HygieneData::with(|data| data.expn_data.clone()); - for (i, data) in all_data.into_iter().enumerate() { - f(i as u32, &data.unwrap_or_else(|| panic!("Missing ExpnData!")))?; - } - Ok(()) -} - pub fn raw_encode_syntax_context( ctxt: SyntaxContext, context: &HygieneEncodeContext, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -16,7 +16,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(crate_visibility_modifier)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(negative_impls)] #![feature(nll)] @@ -1037,10 +1036,6 @@ } impl ExternalSource { - pub fn is_absent(&self) -> bool { - !matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. }) - } - pub fn get_source(&self) -> Option<&Lrc> { match self { ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), @@ -1433,9 +1428,6 @@ self.src.is_none() } - pub fn byte_length(&self) -> u32 { - self.end_pos.0 - self.start_pos.0 - } pub fn count_lines(&self) -> usize { self.lines.len() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/symbol.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/symbol.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_span/src/symbol.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_span/src/symbol.rs 2021-06-17 03:53:51.000000000 +0000 @@ -382,8 +382,11 @@ const_fn, const_fn_floating_point_arithmetic, const_fn_fn_ptr_basics, + const_fn_trait_bound, const_fn_transmute, const_fn_union, + const_fn_unsize, + const_generic_defaults, const_generics, const_generics_defaults, const_if_match, @@ -476,6 +479,7 @@ doc_cfg, doc_keyword, doc_masked, + doc_notable_trait, doc_spotlight, doctest, document_private_items, @@ -629,6 +633,7 @@ impl_macros, impl_trait_in_bindings, import_shadowing, + imported_main, in_band_lifetimes, include, include_bytes, @@ -666,6 +671,7 @@ label_break_value, lang, lang_items, + large_assignments, lateout, lazy_normalization_consts, le, @@ -746,6 +752,7 @@ more_struct_aliases, movbe_target_feature, move_ref_pattern, + move_size_limit, mul, mul_assign, mul_with_overflow, @@ -774,6 +781,7 @@ no, no_builtins, no_core, + no_coverage, no_crate_inject, no_debug, no_default_passes, @@ -793,13 +801,13 @@ non_modrs_mods, none_error, nontemporal_store, - nontrapping_dash_fptoint: "nontrapping-fptoint", noop_method_borrow, noop_method_clone, noop_method_deref, noreturn, nostack, not, + notable_trait, note, object_safe_for_dispatch, of, @@ -845,8 +853,7 @@ partial_ord, passes, pat, - pat2018, - pat2021, + pat_param, path, pattern_parentheses, phantom_data, @@ -896,6 +903,8 @@ profiler_runtime, ptr_guaranteed_eq, ptr_guaranteed_ne, + ptr_null, + ptr_null_mut, ptr_offset_from, pub_macro_rules, pub_restricted, @@ -1002,6 +1011,7 @@ rustc_layout_scalar_valid_range_start, rustc_legacy_const_generics, rustc_macro_transparency, + rustc_main, rustc_mir, rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, @@ -1023,6 +1033,7 @@ rustc_regions, rustc_reservation_impl, rustc_serialize, + rustc_skip_array_during_method_dispatch, rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, @@ -1097,6 +1108,7 @@ simd_reduce_or, simd_reduce_xor, simd_rem, + simd_round, simd_saturating_add, simd_saturating_sub, simd_scatter, @@ -1105,6 +1117,7 @@ simd_shl, simd_shr, simd_sub, + simd_trunc, simd_xor, since, sinf32, @@ -1291,6 +1304,7 @@ vreg, vreg_low16, warn, + wasm_abi, wasm_import_module, wasm_target_feature, while_let, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/legacy.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/legacy.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/legacy.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/legacy.rs 2021-06-17 03:53:51.000000000 +0000 @@ -230,7 +230,7 @@ fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -90,7 +90,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(never_type)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(in_band_lifetimes)] #![recursion_limit = "256"] @@ -198,7 +198,7 @@ // // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if is_foreign - && (tcx.sess.target.arch != "wasm32" + && (!tcx.sess.target.is_like_wasm || !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)) { if let Some(name) = attrs.link_name { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/v0.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/v0.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_symbol_mangling/src/v0.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_symbol_mangling/src/v0.rs 2021-06-17 03:53:51.000000000 +0000 @@ -181,7 +181,7 @@ fn in_binder( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, print_value: impl FnOnce(Self, &T) -> Result, ) -> Result where @@ -318,7 +318,7 @@ // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; @@ -483,7 +483,7 @@ fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { for predicate in predicates { self = self.in_binder(&predicate, |mut cx, predicate| { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/README.md rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/README.md --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/README.md 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/README.md 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -`librustc_target` contains some very low-level details that are +`rustc_target` contains some very low-level details that are specific to different compilation targets and so forth. For more information about how rustc works, see the [rustc dev guide]. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -18,8 +18,7 @@ mod s390x; mod sparc; mod sparc64; -mod wasm32; -mod wasm32_bindgen_compat; +mod wasm; mod x86; mod x86_64; mod x86_win64; @@ -65,14 +64,17 @@ const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const InReg = 1 << 8; + const InReg = 1 << 5; + // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles + // in earlier versions. FIXME: Remove this distinction once possible. + const NoAliasMutRef = 1 << 6; } } } /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum -/// defines if this extension should be zero-extension or sign-extension when necssary. When it is -/// not necesary to extend the argument, this enum is ignored. +/// defines if this extension should be zero-extension or sign-extension when necessary. When it is +/// not necessary to extend the argument, this enum is ignored. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ArgExtension { None, @@ -644,11 +646,14 @@ "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" => match cx.target_spec().os.as_str() { - "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self), - _ => wasm32_bindgen_compat::compute_abi_info(self), - }, - "asmjs" => wasm32::compute_abi_info(cx, self), + "wasm32" | "wasm64" => { + if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + wasm::compute_wasm_abi_info(self) + } else { + wasm::compute_c_abi_info(cx, self) + } + } + "asmjs" => wasm::compute_c_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{ArgAbi, FnAbi}; - -fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { - if !fn_abi.ret.is_ignore() { - classify_ret(&mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(arg); - } -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm32.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -use crate::abi::call::{ArgAbi, FnAbi, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; - -fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout, -{ - if val.layout.is_aggregate() { - if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { - let size = val.layout.size; - if unit.size == size { - val.cast_to(Uniform { unit, total: size }); - return true; - } - } - } - false -} - -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout, -{ - ret.extend_integer_width_to(32); - if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) { - ret.make_indirect(); - } -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout, -{ - arg.extend_integer_width_to(32); - if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) { - arg.make_indirect_byval(); - } -} - -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout, -{ - if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(cx, arg); - } -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/call/wasm.rs 2021-06-17 03:53:51.000000000 +0000 @@ -0,0 +1,83 @@ +use crate::abi::call::{ArgAbi, FnAbi, Uniform}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; + +fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + if val.layout.is_aggregate() { + if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { + let size = val.layout.size; + if unit.size == size { + val.cast_to(Uniform { unit, total: size }); + return true; + } + } + } + false +} + +fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + ret.extend_integer_width_to(32); + if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) { + ret.make_indirect(); + } +} + +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + arg.extend_integer_width_to(32); + if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) { + arg.make_indirect_byval(); + } +} + +/// The purpose of this ABI is to match the C ABI (aka clang) exactly. +pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +where + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout, +{ + if !fn_abi.ret.is_ignore() { + classify_ret(cx, &mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(cx, arg); + } +} + +/// The purpose of this ABI is for matching the WebAssembly standard. This +/// intentionally diverges from the C ABI and is specifically crafted to take +/// advantage of LLVM's support of multiple returns in WebAssembly. +pub fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } + + fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + ret.extend_integer_width_to(32); + } + + fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + arg.extend_integer_width_to(32); + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/abi/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/abi/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1112,7 +1112,7 @@ /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. Frozen, - /// `&mut T`, when we know `noalias` is safe for LLVM. + /// `&mut T` which is `noalias` but not `readonly`. UniqueBorrowed, /// `Box`, unlike `UniqueBorrowed`, it also has `noalias` on returns. diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/arm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/arm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/arm.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/arm.rs 2021-06-17 03:53:51.000000000 +0000 @@ -68,7 +68,6 @@ _arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if !frame_pointer_is_r7(has_feature, target) { Err("the frame pointer (r11) cannot be used as an operand for inline asm") @@ -81,7 +80,6 @@ _arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if frame_pointer_is_r7(has_feature, target) { Err("the frame pointer (r7) cannot be used as an operand for inline asm") diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -90,7 +90,7 @@ match name { $( $($alias)|* | $reg_name => { - $($filter(_arch, &mut _has_feature, _target, false)?;)? + $($filter(_arch, &mut _has_feature, _target)?;)? Ok(Self::$reg) } )* @@ -114,7 +114,7 @@ #[allow(unused_imports)] use super::{InlineAsmReg, InlineAsmRegClass}; $( - if $($filter(_arch, &mut _has_feature, _target, true).is_ok() &&)? true { + if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true { if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/riscv.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/riscv.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/riscv.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/riscv.rs 2021-06-17 03:53:51.000000000 +0000 @@ -52,7 +52,6 @@ _arch: InlineAsmArch, mut has_feature: impl FnMut(&str) -> bool, _target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if has_feature("e") { Err("register can't be used with the `e` target feature") diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/x86.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/x86.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/asm/x86.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/asm/x86.rs 2021-06-17 03:53:51.000000000 +0000 @@ -133,7 +133,6 @@ arch: InlineAsmArch, _has_feature: impl FnMut(&str) -> bool, _target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { match arch { InlineAsmArch::X86 => Err("register is only available on x86_64"), @@ -146,13 +145,9 @@ arch: InlineAsmArch, _has_feature: impl FnMut(&str) -> bool, _target: &Target, - allocating: bool, ) -> Result<(), &'static str> { match arch { - InlineAsmArch::X86_64 if allocating => { - // The error message isn't actually used... - Err("high byte registers are not allocated by reg_byte") - } + InlineAsmArch::X86_64 => Err("high byte registers cannot be used as an operand on x86_64"), _ => Ok(()), } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -9,7 +9,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(nll)] #![feature(never_type)] @@ -28,5 +27,5 @@ /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext {} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,11 +1,12 @@ -use crate::spec::{LinkerFlavor, Target, TargetOptions}; +use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "apple-a12".to_string(); base.max_atomic_width = Some(128); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // Clang automatically chooses a more specific target based on diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_fuchsia.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_fuchsia.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_fuchsia.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_fuchsia.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,8 +1,9 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::fuchsia_base::opts(); base.max_atomic_width = Some(128); + base.supported_sanitizers = SanitizerSet::ADDRESS; Target { llvm_target: "aarch64-fuchsia".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_linux_android.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_linux_android.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_linux_android.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_linux_android.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a // for target ABI requirements. @@ -9,6 +9,7 @@ // As documented in http://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. base.features = "+neon,+fp-armv8".to_string(); + base.supported_sanitizers = SanitizerSet::HWADDRESS; Target { llvm_target: "aarch64-linux-android".to_string(), pointer_width: 64, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,8 +1,13 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(128); + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD + | SanitizerSet::HWADDRESS; Target { llvm_target: "aarch64-unknown-linux-gnu".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/abi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/abi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/abi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/abi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -34,6 +34,7 @@ AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + Wasm, // Multiplatform / generic ABIs System { unwind: bool }, @@ -83,6 +84,7 @@ generic: false, }, AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false }, + AbiData { abi: Abi::Wasm, name: "wasm", generic: false }, // Cross-platform ABIs AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true }, AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true }, @@ -131,13 +133,14 @@ AvrInterrupt => 18, AvrNonBlockingInterrupt => 19, CCmseNonSecureCall => 20, + Wasm => 21, // Cross-platform ABIs - System { unwind: false } => 21, - System { unwind: true } => 22, - RustIntrinsic => 23, - RustCall => 24, - PlatformIntrinsic => 25, - Unadjusted => 26, + System { unwind: false } => 22, + System { unwind: true } => 23, + RustIntrinsic => 24, + RustCall => 25, + PlatformIntrinsic => 26, + Unadjusted => 27, }; debug_assert!( AbiDatas diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/android_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/android_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/android_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/android_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,13 +6,16 @@ // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--allow-multiple-definition".to_string()); base.dwarf_version = Some(2); base.position_independent_executables = true; base.has_elf_tls = false; - base.requires_uwtable = true; + // 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`). + base.default_uwtable = true; base.crt_static_respected = false; base } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/apple_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/apple_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/apple_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/apple_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{LinkArgs, SplitDebuginfo, TargetOptions}; +use crate::spec::{SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -27,10 +27,8 @@ is_like_osx: true, dwarf_version: Some(2), has_rpath: true, - dll_prefix: "lib".to_string(), dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), - pre_link_args: LinkArgs::new(), has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -12,7 +12,7 @@ let mut base = super::android_base::opts(); base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); Target { llvm_target: "armv7-none-linux-android".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -14,7 +14,6 @@ options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -13,7 +13,6 @@ options: TargetOptions { features: "+v7,+thumb2,+soft-float,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -17,7 +17,6 @@ // target. options: TargetOptions { features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -18,7 +18,6 @@ options: TargetOptions { features: "+v7,+thumb2,+soft-float,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -11,7 +11,6 @@ options: TargetOptions { env: "eabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "__mcount".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -10,7 +10,6 @@ options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/avr_gnu_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/avr_gnu_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/avr_gnu_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/avr_gnu_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -15,28 +15,12 @@ exe_suffix: ".elf".to_string(), linker: Some("avr-gcc".to_owned()), - dynamic_linking: false, executables: true, linker_is_gnu: true, - has_rpath: false, - position_independent_executables: false, eh_frame_header: false, - pre_link_args: vec![( - LinkerFlavor::Gcc, - vec![ - format!("-mmcu={}", target_cpu), - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - ], - )] - .into_iter() - .collect(), + pre_link_args: vec![(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu)])] + .into_iter() + .collect(), late_link_args: vec![(LinkerFlavor::Gcc, vec!["-lgcc".to_owned()])] .into_iter() .collect(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/dragonfly_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/dragonfly_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/dragonfly_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/dragonfly_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "dragonfly".to_string(), dynamic_linking: true, @@ -22,7 +8,6 @@ os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, dwarf_version: Some(2), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/freebsd_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/freebsd_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/freebsd_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/freebsd_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "freebsd".to_string(), dynamic_linking: true, @@ -22,7 +8,6 @@ os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/fuchsia_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/fuchsia_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/fuchsia_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/fuchsia_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -23,13 +23,11 @@ os: "fuchsia".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), - lld_flavor: LldFlavor::Ld, dynamic_linking: true, executables: true, os_family: Some("unix".to_string()), is_like_fuchsia: true, linker_is_gnu: true, - has_rpath: false, pre_link_args, pre_link_objects: crt_objects::new(&[ (LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/haiku_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/haiku_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/haiku_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/haiku_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -5,7 +5,6 @@ os: "haiku".to_string(), dynamic_linking: true, executables: true, - has_rpath: false, os_family: Some("unix".to_string()), relro_level: RelroLevel::Full, linker_is_gnu: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,5 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy}; -use crate::spec::{RelocModel, TargetOptions, TlsModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -19,8 +18,6 @@ panic_strategy: PanicStrategy::Abort, position_independent_executables: true, static_position_independent_executables: true, - relocation_model: RelocModel::Pic, - os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_kernel_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_kernel_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_kernel_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hermit_kernel_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,5 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy}; -use crate::spec::{RelocModel, TargetOptions, TlsModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -20,8 +19,6 @@ panic_strategy: PanicStrategy::Abort, position_independent_executables: true, static_position_independent_executables: true, - relocation_model: RelocModel::Pic, - os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, Target}; +use crate::spec::Target; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); @@ -8,15 +8,11 @@ base.features = "-small-data,+hvx-length128b".to_string(); base.crt_static_default = false; - base.atomic_cas = true; base.has_rpath = true; base.linker_is_gnu = false; base.dynamic_linking = true; base.executables = true; - base.pre_link_args = LinkArgs::new(); - base.post_link_args = LinkArgs::new(); - Target { llvm_target: "hexagon-unknown-linux-musl".to_string(), pointer_width: 32, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -12,8 +12,8 @@ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--large-address-aware".to_string()); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs 2021-06-17 03:53:51.000000000 +0000 @@ -14,10 +14,10 @@ // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers "/SAFESEH".to_string(), ]; - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::freebsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - let pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); pre_link_args.push("-m32".to_string()); pre_link_args.push("-Wl,-znotext".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::linux_gnu_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,8 +4,8 @@ let mut base = super::linux_musl_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::netbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,8 +4,8 @@ let mut base = super::openbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-fuse-ld=lld".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -11,8 +11,8 @@ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--large-address-aware".to_string()); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::vxworks_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/l4re_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/l4re_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/l4re_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/l4re_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions}; +use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions}; //use std::process::Command; // Use GCC to locate code for crt* libraries from the host, not from L4Re. Note @@ -13,18 +13,13 @@ //} pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert(LinkerFlavor::Gcc, vec![]); - TargetOptions { os: "l4re".to_string(), env: "uclibc".to_string(), linker_flavor: LinkerFlavor::Ld, executables: true, - has_elf_tls: false, panic_strategy: PanicStrategy::Abort, linker: Some("ld".to_string()), - pre_link_args: args, os_family: Some("unix".to_string()), ..Default::default() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/linux_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/linux_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/linux_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/linux_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,23 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "linux".to_string(), dynamic_linking: true, @@ -25,7 +8,6 @@ os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, has_elf_tls: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/linux_kernel_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/linux_kernel_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/linux_kernel_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/linux_kernel_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,14 +1,6 @@ -use crate::spec::{ - LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions, -}; +use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions}; pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Gcc, - vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()], - ); - TargetOptions { env: "gnu".to_string(), disable_redzone: true, @@ -21,7 +13,6 @@ needs_plt: true, relro_level: RelroLevel::Full, relocation_model: RelocModel::Static, - pre_link_args, ..Default::default() } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -37,6 +37,7 @@ use crate::abi::Endian; use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_serialize::json::{Json, ToJson}; use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeMap; @@ -78,7 +79,7 @@ mod thumb_base; mod uefi_msvc_base; mod vxworks_base; -mod wasm32_base; +mod wasm_base; mod windows_gnu_base; mod windows_msvc_base; mod windows_uwp_gnu_base; @@ -511,38 +512,6 @@ } } -macro_rules! supported_targets { - ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { - $(mod $module;)+ - - /// List of supported targets - pub const TARGETS: &[&str] = &[$($($triple),+),+]; - - fn load_builtin(target: &str) -> Option { - let mut t = match target { - $( $($triple)|+ => $module::target(), )+ - _ => return None, - }; - t.is_builtin = true; - debug!("got builtin target: {:?}", t); - Some(t) - } - - #[cfg(test)] - mod tests { - mod tests_impl; - - // Cannot put this into a separate file without duplication, make an exception. - $( - #[test] // `#[test]` - fn $module() { - tests_impl::test_target(super::$module::target()); - } - )+ - } - }; -} - #[derive(Clone, Debug, PartialEq, Eq)] pub enum StackProbeType { /// Don't emit any stack probes. @@ -620,6 +589,117 @@ } } +bitflags::bitflags! { + #[derive(Default, Encodable, Decodable)] + pub struct SanitizerSet: u8 { + const ADDRESS = 1 << 0; + const LEAK = 1 << 1; + const MEMORY = 1 << 2; + const THREAD = 1 << 3; + const HWADDRESS = 1 << 4; + } +} + +impl SanitizerSet { + /// Return sanitizer's name + /// + /// Returns none if the flags is a set of sanitizers numbering not exactly one. + fn as_str(self) -> Option<&'static str> { + Some(match self { + SanitizerSet::ADDRESS => "address", + SanitizerSet::LEAK => "leak", + SanitizerSet::MEMORY => "memory", + SanitizerSet::THREAD => "thread", + SanitizerSet::HWADDRESS => "hwaddress", + _ => return None, + }) + } +} + +/// Formats a sanitizer set as a comma separated list of sanitizers' names. +impl fmt::Display for SanitizerSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut first = true; + for s in *self { + let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s)); + if !first { + f.write_str(", ")?; + } + f.write_str(name)?; + first = false; + } + Ok(()) + } +} + +impl IntoIterator for SanitizerSet { + type Item = SanitizerSet; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + [ + SanitizerSet::ADDRESS, + SanitizerSet::LEAK, + SanitizerSet::MEMORY, + SanitizerSet::THREAD, + SanitizerSet::HWADDRESS, + ] + .iter() + .copied() + .filter(|&s| self.contains(s)) + .collect::>() + .into_iter() + } +} + +impl HashStable for SanitizerSet { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.bits().hash_stable(ctx, hasher); + } +} + +impl ToJson for SanitizerSet { + fn to_json(&self) -> Json { + self.into_iter() + .map(|v| Some(v.as_str()?.to_json())) + .collect::>>() + .unwrap_or(Vec::new()) + .to_json() + } +} + +macro_rules! supported_targets { + ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { + $(mod $module;)+ + + /// List of supported targets + pub const TARGETS: &[&str] = &[$($($triple),+),+]; + + fn load_builtin(target: &str) -> Option { + let mut t = match target { + $( $($triple)|+ => $module::target(), )+ + _ => return None, + }; + t.is_builtin = true; + debug!("got builtin target: {:?}", t); + Some(t) + } + + #[cfg(test)] + mod tests { + mod tests_impl; + + // Cannot put this into a separate file without duplication, make an exception. + $( + #[test] // `#[test]` + fn $module() { + tests_impl::test_target(super::$module::target()); + } + )+ + } + }; +} + supported_targets! { ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu), ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32), @@ -762,6 +842,7 @@ ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm64-unknown-unknown", wasm64_unknown_unknown), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), @@ -996,6 +1077,8 @@ pub is_like_emscripten: bool, /// Whether the target toolchain is like Fuchsia's. pub is_like_fuchsia: bool, + /// Whether a target toolchain is like WASM. + pub is_like_wasm: bool, /// Version of DWARF to use if not using the default. /// Useful because some platforms (osx, bsd) only want up to DWARF2. pub dwarf_version: Option, @@ -1111,6 +1194,10 @@ /// unwinders. pub requires_uwtable: bool, + /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables` + /// is not specified and `uwtable` is not required on this target. + pub default_uwtable: bool, + /// Whether or not SIMD types are passed by reference in the Rust ABI, /// typically required if a target can be compiled with a mixed set of /// target features. This is `true` by default, and `false` for targets like @@ -1160,6 +1247,16 @@ /// How to handle split debug information, if at all. Specifying `None` has /// target-specific meaning. pub split_debuginfo: SplitDebuginfo, + + /// The sanitizers supported by this target + /// + /// Note that the support here is at a codegen level. If the machine code with sanitizer + /// enabled can generated on this target, but the necessary supporting libraries are not + /// distributed with the target, the sanitizer should still appear in this list for the target. + pub supported_sanitizers: SanitizerSet, + + /// If present it's a default value to use for adjusting the C ABI. + pub default_adjusted_cabi: Option, } impl Default for TargetOptions { @@ -1204,6 +1301,7 @@ is_like_emscripten: false, is_like_msvc: false, is_like_fuchsia: false, + is_like_wasm: false, dwarf_version: None, linker_is_gnu: false, allows_weak_linkage: true, @@ -1248,6 +1346,7 @@ default_hidden_visibility: false, emit_debug_gdb_scripts: true, requires_uwtable: false, + default_uwtable: false, simd_types_indirect: true, limit_rdylib_exports: true, override_export_symbols: None, @@ -1260,6 +1359,8 @@ eh_frame_header: true, has_thumb_interworking: false, split_debuginfo: SplitDebuginfo::Off, + supported_sanitizers: SanitizerSet::empty(), + default_adjusted_cabi: None, } } } @@ -1311,6 +1412,9 @@ Abi::C { unwind: false } } } + + Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }), + abi => abi, } } @@ -1342,8 +1446,8 @@ let get_req_field = |name: &str| { obj.find(name) - .map(|s| s.as_string()) - .and_then(|os| os.map(|s| s.to_string())) + .and_then(Json::as_string) + .map(str::to_string) .ok_or_else(|| format!("Field {} in target specification is required", name)) }; @@ -1546,6 +1650,24 @@ )), }).unwrap_or(Ok(())) } ); + ($key_name:ident, SanitizerSet) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| { + for s in a { + base.$key_name |= match s.as_string() { + Some("address") => SanitizerSet::ADDRESS, + Some("leak") => SanitizerSet::LEAK, + Some("memory") => SanitizerSet::MEMORY, + Some("thread") => SanitizerSet::THREAD, + Some("hwaddress") => SanitizerSet::HWADDRESS, + Some(s) => return Some(Err(format!("unknown sanitizer {}", s))), + _ => return Some(Err(format!("not a string: {:?}", s))), + }; + } + Some(Ok(())) + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, crt_objects_fallback) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { @@ -1627,6 +1749,16 @@ } } } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match lookup_abi(s) { + Some(abi) => base.$key_name = Some(abi), + _ => return Some(Err(format!("'{}' is not a valid value for abi", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); } if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { @@ -1678,6 +1810,7 @@ key!(is_like_msvc, bool); key!(is_like_emscripten, bool); key!(is_like_fuchsia, bool); + key!(is_like_wasm, bool); key!(dwarf_version, Option); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); @@ -1711,6 +1844,7 @@ key!(default_hidden_visibility, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); + key!(default_uwtable, bool); key!(simd_types_indirect, bool); key!(limit_rdylib_exports, bool); key!(override_export_symbols, opt_list); @@ -1723,6 +1857,8 @@ key!(eh_frame_header, bool); key!(has_thumb_interworking, bool); key!(split_debuginfo, SplitDebuginfo)?; + key!(supported_sanitizers, SanitizerSet)?; + key!(default_adjusted_cabi, Option)?; // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -1914,6 +2050,7 @@ target_option_val!(is_like_msvc); target_option_val!(is_like_emscripten); target_option_val!(is_like_fuchsia); + target_option_val!(is_like_wasm); target_option_val!(dwarf_version); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); @@ -1947,6 +2084,7 @@ target_option_val!(default_hidden_visibility); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); + target_option_val!(default_uwtable); target_option_val!(simd_types_indirect); target_option_val!(limit_rdylib_exports); target_option_val!(override_export_symbols); @@ -1959,6 +2097,11 @@ target_option_val!(eh_frame_header); target_option_val!(has_thumb_interworking); target_option_val!(split_debuginfo); + target_option_val!(supported_sanitizers); + + if let Some(abi) = self.default_adjusted_cabi { + d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); + } if default.unsupported_abis != self.unsupported_abis { d.insert( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/msvc_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/msvc_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/msvc_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/msvc_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -5,13 +5,6 @@ // Suppress the verbose logo and authorship debugging output, which would needlessly // clog any log files. "/NOLOGO".to_string(), - // Tell the compiler that non-code sections can be marked as non-executable, - // including stack pages. - // UEFI is fully compatible to non-executable data pages. - // In fact, firmware might enforce this, so we better let the linker know about this, - // so it will fail if the compiler ever tries placing code on the stack - // (e.g., trampoline constructs and alike). - "/NXCOMPAT".to_string(), ]; let mut pre_link_args = LinkArgs::new(); pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/netbsd_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/netbsd_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/netbsd_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/netbsd_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,18 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - ], - ); - TargetOptions { os: "netbsd".to_string(), dynamic_linking: true, @@ -21,7 +9,6 @@ linker_is_gnu: true, no_default_libraries: false, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, use_ctors_section: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/openbsd_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/openbsd_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/openbsd_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/openbsd_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "openbsd".to_string(), dynamic_linking: true, @@ -23,7 +9,6 @@ linker_is_gnu: true, has_rpath: true, abi_return_struct_as_int: true, - pre_link_args: args, position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64le".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64le".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,8 +3,8 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,8 +3,8 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string()); base.max_atomic_width = Some(32); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/redox_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/redox_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/redox_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/redox_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,23 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "redox".to_string(), env: "relibc".to_string(), @@ -26,7 +9,6 @@ os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, has_elf_tls: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -13,7 +13,6 @@ linker: Some("rust-lld".to_string()), cpu: "generic-rv32".to_string(), max_atomic_width: Some(32), - atomic_cas: true, features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -14,7 +14,6 @@ cpu: "generic-rv32".to_string(), max_atomic_width: Some(0), atomic_cas: false, - features: String::new(), executables: true, panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -14,7 +14,6 @@ llvm_abiname: "lp64d".to_string(), cpu: "generic-rv64".to_string(), max_atomic_width: Some(64), - atomic_cas: true, features: "+m,+a,+f,+d,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -13,7 +13,6 @@ linker: Some("rust-lld".to_string()), cpu: "generic-rv64".to_string(), max_atomic_width: Some(64), - atomic_cas: true, features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "v9".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -5,7 +5,7 @@ let mut base = super::openbsd_base::opts(); base.endian = Endian::Big; base.cpu = "v9".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,7 +6,7 @@ base.endian = Endian::Big; base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".to_string()); Target { llvm_target: "sparc-unknown-linux-gnu".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/tests/tests_impl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/tests/tests_impl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/tests/tests_impl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/tests/tests_impl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -50,6 +50,7 @@ // and you certainly want "unknown" for the OS name. fn can_use_os_unknown(&self) -> bool { self.llvm_target == "wasm32-unknown-unknown" + || self.llvm_target == "wasm64-unknown-unknown" || (self.env == "sgx" && self.vendor == "fortanix") } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -45,9 +45,6 @@ main_needs_argc_argv: false, - // No thread-local storage (just use a static Cell) - has_elf_tls: false, - // don't have atomic compare-and-swap atomic_cas: false, has_thumb_interworking: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs 2021-06-17 03:53:51.000000000 +0000 @@ -11,10 +11,10 @@ // where necessary, but this is not the observed behavior. // Disabling the LBR optimization works around the issue. let pre_link_args_msvc = "/OPT:NOLBR".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .push(pre_link_args_msvc); // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is @@ -29,7 +29,6 @@ options: TargetOptions { features: "+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs 2021-06-17 03:53:51.000000000 +0000 @@ -16,7 +16,6 @@ arch: "arm".to_string(), options: TargetOptions { features: "+vfp3,+neon".to_string(), - cpu: "generic".to_string(), unsupported_abis: super::arm_base::unsupported_abis(), ..base }, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -12,7 +12,7 @@ let mut base = super::android_base::opts(); base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); Target { llvm_target: "armv7-none-linux-android".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -17,7 +17,6 @@ options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -21,7 +21,6 @@ // target. options: TargetOptions { features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/uefi_msvc_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/uefi_msvc_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/uefi_msvc_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/uefi_msvc_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -30,10 +30,10 @@ // exit (default for applications). "/subsystem:efi_application".to_string(), ]; - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); TargetOptions { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/vxworks_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/vxworks_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/vxworks_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/vxworks_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,21 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - ], - ); - TargetOptions { os: "vxworks".to_string(), env: "gnu".to_string(), @@ -27,8 +12,6 @@ os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, - position_independent_executables: false, has_elf_tls: true, crt_static_default: true, crt_static_respected: true, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_base.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -use super::crt_objects::CrtObjectsFallback; -use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; -use std::collections::BTreeMap; - -pub fn options() -> TargetOptions { - let mut lld_args = Vec::new(); - let mut clang_args = Vec::new(); - let mut arg = |arg: &str| { - lld_args.push(arg.to_string()); - clang_args.push(format!("-Wl,{}", arg)); - }; - - // By default LLD only gives us one page of stack (64k) which is a - // little small. Default to a larger stack closer to other PC platforms - // (1MB) and users can always inject their own link-args to override this. - arg("-z"); - arg("stack-size=1048576"); - - // By default LLD's memory layout is: - // - // 1. First, a blank page - // 2. Next, all static data - // 3. Finally, the main stack (which grows down) - // - // This has the unfortunate consequence that on stack overflows you - // corrupt static data and can cause some exceedingly weird bugs. To - // help detect this a little sooner we instead request that the stack is - // placed before static data. - // - // This means that we'll generate slightly larger binaries as references - // to static data will take more bytes in the ULEB128 encoding, but - // stack overflow will be guaranteed to trap as it underflows instead of - // corrupting static data. - arg("--stack-first"); - - // FIXME we probably shouldn't pass this but instead pass an explicit list - // of symbols we'll allow to be undefined. We don't currently have a - // mechanism of knowing, however, which symbols are intended to be imported - // from the environment and which are intended to be imported from other - // objects linked elsewhere. This is a coarse approximation but is sure to - // hide some bugs and frustrate someone at some point, so we should ideally - // work towards a world where we can explicitly list symbols that are - // supposed to be imported and have all other symbols generate errors if - // they remain undefined. - arg("--allow-undefined"); - - // Rust code should never have warnings, and warnings are often - // indicative of bugs, let's prevent them. - arg("--fatal-warnings"); - - // LLD only implements C++-like demangling, which doesn't match our own - // mangling scheme. Tell LLD to not demangle anything and leave it up to - // us to demangle these symbols later. Currently rustc does not perform - // further demangling, but tools like twiggy and wasm-bindgen are intended - // to do so. - arg("--no-demangle"); - - let mut pre_link_args = BTreeMap::new(); - pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args); - pre_link_args.insert(LinkerFlavor::Gcc, clang_args); - - TargetOptions { - // we allow dynamic linking, but only cdylibs. Basically we allow a - // final library artifact that exports some symbols (a wasm module) but - // we don't allow intermediate `dylib` crate types - dynamic_linking: true, - only_cdylib: true, - - // This means we'll just embed a `#[start]` function in the wasm module - executables: true, - - // relatively self-explanatory! - exe_suffix: ".wasm".to_string(), - dll_prefix: String::new(), - dll_suffix: ".wasm".to_string(), - linker_is_gnu: false, - eh_frame_header: false, - - max_atomic_width: Some(64), - - // Unwinding doesn't work right now, so the whole target unconditionally - // defaults to panic=abort. Note that this is guaranteed to change in - // the future once unwinding is implemented. Don't rely on this as we're - // basically guaranteed to change it once WebAssembly supports - // exceptions. - panic_strategy: PanicStrategy::Abort, - - // Wasm doesn't have atomics yet, so tell LLVM that we're in a single - // threaded model which will legalize atomics to normal operations. - singlethread: true, - - // no dynamic linking, no need for default visibility! - default_hidden_visibility: true, - - // Symbol visibility takes care of this for the WebAssembly. - // Additionally the only known linker, LLD, doesn't support the script - // arguments just yet - limit_rdylib_exports: false, - - // we use the LLD shipped with the Rust toolchain by default - linker: Some("rust-lld".to_owned()), - lld_flavor: LldFlavor::Wasm, - - // No need for indirection here, simd types can always be passed by - // value as the whole module either has simd or not, which is different - // from x86 (for example) where programs can have functions that don't - // enable simd features. - simd_types_indirect: false, - - pre_link_args, - - crt_objects_fallback: Some(CrtObjectsFallback::Wasm), - - // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when - // PIC code is implemented this has quite a drastric effect if it stays - // at the default, `pic`. In an effort to keep wasm binaries as minimal - // as possible we're defaulting to `static` for now, but the hope is - // that eventually we can ship a `pic`-compatible standard library which - // works with `static` as well (or works with some method of generating - // non-relative calls and such later on). - relocation_model: RelocModel::Static, - - // 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 - // `local-exec` as that's all that's implemented in LLVM today for wasm. - has_elf_tls: true, - tls_model: TlsModel::LocalExec, - - // gdb scripts don't work on wasm blobs - emit_debug_gdb_scripts: false, - - ..Default::default() - } -} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,10 +1,10 @@ -use super::wasm32_base; +use super::wasm_base; use super::{LinkArgs, LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); - let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Rust really needs a way for users to specify exports and imports in // the source code. --export-dynamic isn't the right tool for this job, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs 2021-06-17 03:53:51.000000000 +0000 @@ -10,14 +10,26 @@ //! This target is more or less managed by the Rust and WebAssembly Working //! Group nowadays at . -use super::wasm32_base; +use super::wasm_base; use super::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::abi::Abi; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); options.os = "unknown".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); - let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + + // This is a default for backwards-compatibility with the original + // definition of this target oh-so-long-ago. Once the "wasm" ABI is + // stable and the wasm-bindgen project has switched to using it then there's + // no need for this and it can be removed. + // + // Currently this is the reason that this target's ABI is mismatched with + // clang's ABI. This means that, in the limit, you can't merge C and Rust + // code on this target due to this ABI mismatch. + options.default_adjusted_cabi = Some(Abi::Wasm); + + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Make sure clang uses LLD as its linker and is configured appropriately // otherwise @@ -35,7 +47,7 @@ clang_args.push("-Wl,--export-dynamic".to_string()); // Add the flags to wasm-ld's args too. - let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); + let lld_args = options.pre_link_args.entry(LinkerFlavor::Lld(LldFlavor::Wasm)).or_default(); lld_args.push("--no-entry".to_string()); lld_args.push("--export-dynamic".to_string()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_wasi.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_wasi.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_wasi.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm32_wasi.rs 2021-06-17 03:53:51.000000000 +0000 @@ -72,11 +72,11 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::wasm32_base; +use super::wasm_base; use super::{crt_objects, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); options.os = "wasi".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs 2021-06-17 03:53:51.000000000 +0000 @@ -0,0 +1,39 @@ +//! A "bare wasm" target representing a WebAssembly output that makes zero +//! assumptions about its environment. +//! +//! The `wasm64-unknown-unknown` target is intended to encapsulate use cases +//! that do not rely on any imported functionality. The binaries generated are +//! entirely self-contained by default when using the standard library. Although +//! the standard library is available, most of it returns an error immediately +//! (e.g. trying to create a TCP stream or something like that). + +use super::wasm_base; +use super::{LinkerFlavor, LldFlavor, Target}; + +pub fn target() -> Target { + let mut options = wasm_base::options(); + options.os = "unknown".to_string(); + options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); + let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + + // Make sure clang uses LLD as its linker and is configured appropriately + // otherwise + clang_args.push("--target=wasm64-unknown-unknown".to_string()); + + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + clang_args.push("-Wl,--no-entry".to_string()); + options + .pre_link_args + .get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)) + .unwrap() + .push("--no-entry".to_string()); + + Target { + llvm_target: "wasm64-unknown-unknown".to_string(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".to_string(), + arch: "wasm64".to_string(), + options, + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/wasm_base.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/wasm_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -0,0 +1,137 @@ +use super::crt_objects::CrtObjectsFallback; +use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; +use std::collections::BTreeMap; + +pub fn options() -> TargetOptions { + let mut lld_args = Vec::new(); + let mut clang_args = Vec::new(); + let mut arg = |arg: &str| { + lld_args.push(arg.to_string()); + clang_args.push(format!("-Wl,{}", arg)); + }; + + // By default LLD only gives us one page of stack (64k) which is a + // little small. Default to a larger stack closer to other PC platforms + // (1MB) and users can always inject their own link-args to override this. + arg("-z"); + arg("stack-size=1048576"); + + // By default LLD's memory layout is: + // + // 1. First, a blank page + // 2. Next, all static data + // 3. Finally, the main stack (which grows down) + // + // This has the unfortunate consequence that on stack overflows you + // corrupt static data and can cause some exceedingly weird bugs. To + // help detect this a little sooner we instead request that the stack is + // placed before static data. + // + // This means that we'll generate slightly larger binaries as references + // to static data will take more bytes in the ULEB128 encoding, but + // stack overflow will be guaranteed to trap as it underflows instead of + // corrupting static data. + arg("--stack-first"); + + // FIXME we probably shouldn't pass this but instead pass an explicit list + // of symbols we'll allow to be undefined. We don't currently have a + // mechanism of knowing, however, which symbols are intended to be imported + // from the environment and which are intended to be imported from other + // objects linked elsewhere. This is a coarse approximation but is sure to + // hide some bugs and frustrate someone at some point, so we should ideally + // work towards a world where we can explicitly list symbols that are + // supposed to be imported and have all other symbols generate errors if + // they remain undefined. + arg("--allow-undefined"); + + // Rust code should never have warnings, and warnings are often + // indicative of bugs, let's prevent them. + arg("--fatal-warnings"); + + // LLD only implements C++-like demangling, which doesn't match our own + // mangling scheme. Tell LLD to not demangle anything and leave it up to + // us to demangle these symbols later. Currently rustc does not perform + // further demangling, but tools like twiggy and wasm-bindgen are intended + // to do so. + arg("--no-demangle"); + + let mut pre_link_args = BTreeMap::new(); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args); + pre_link_args.insert(LinkerFlavor::Gcc, clang_args); + + TargetOptions { + is_like_wasm: true, + + // we allow dynamic linking, but only cdylibs. Basically we allow a + // final library artifact that exports some symbols (a wasm module) but + // we don't allow intermediate `dylib` crate types + dynamic_linking: true, + only_cdylib: true, + + // This means we'll just embed a `#[start]` function in the wasm module + executables: true, + + // relatively self-explanatory! + exe_suffix: ".wasm".to_string(), + dll_prefix: String::new(), + dll_suffix: ".wasm".to_string(), + eh_frame_header: false, + + max_atomic_width: Some(64), + + // Unwinding doesn't work right now, so the whole target unconditionally + // defaults to panic=abort. Note that this is guaranteed to change in + // the future once unwinding is implemented. Don't rely on this as we're + // basically guaranteed to change it once WebAssembly supports + // exceptions. + panic_strategy: PanicStrategy::Abort, + + // Wasm doesn't have atomics yet, so tell LLVM that we're in a single + // threaded model which will legalize atomics to normal operations. + singlethread: true, + + // no dynamic linking, no need for default visibility! + default_hidden_visibility: true, + + // Symbol visibility takes care of this for the WebAssembly. + // Additionally the only known linker, LLD, doesn't support the script + // arguments just yet + limit_rdylib_exports: false, + + // we use the LLD shipped with the Rust toolchain by default + linker: Some("rust-lld".to_owned()), + lld_flavor: LldFlavor::Wasm, + + // No need for indirection here, simd types can always be passed by + // value as the whole module either has simd or not, which is different + // from x86 (for example) where programs can have functions that don't + // enable simd features. + simd_types_indirect: false, + + pre_link_args, + + crt_objects_fallback: Some(CrtObjectsFallback::Wasm), + + // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when + // PIC code is implemented this has quite a drastric effect if it stays + // at the default, `pic`. In an effort to keep wasm binaries as minimal + // as possible we're defaulting to `static` for now, but the hope is + // that eventually we can ship a `pic`-compatible standard library which + // works with `static` as well (or works with some method of generating + // non-relative calls and such later on). + relocation_model: RelocModel::Static, + + // 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 + // `local-exec` as that's all that's implemented in LLVM today for wasm. + has_elf_tls: true, + tls_model: TlsModel::LocalExec, + + // gdb scripts don't work on wasm blobs + emit_debug_gdb_scripts: false, + + ..Default::default() + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/windows_gnu_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/windows_gnu_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/windows_gnu_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/windows_gnu_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -9,8 +9,6 @@ // Tell GCC to avoid linker plugins, because we are not bundling // them with Windows installer, and Rust does its own LTO anyways. "-fno-use-linker-plugin".to_string(), - // Always enable DEP (NX bit) when it is available - "-Wl,--nxcompat".to_string(), // Enable ASLR "-Wl,--dynamicbase".to_string(), // ASLR will rebase it anyway so leaving that option enabled only leads to confusion @@ -73,8 +71,6 @@ dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), - staticlib_prefix: "lib".to_string(), - staticlib_suffix: ".a".to_string(), os_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs 2021-06-17 03:53:51.000000000 +0000 @@ -5,10 +5,10 @@ opts.vendor = "uwp".to_string(); let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()]; - opts.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); opts.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); opts diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -12,6 +12,7 @@ base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,12 +1,9 @@ use std::iter; -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, Target, TargetOptions}; pub fn target() -> Target { const PRE_LINK_ARGS: &[&str] = &[ - "--as-needed", - "-z", - "noexecstack", "-e", "elf_entry", "-Bstatic", @@ -59,12 +56,10 @@ env: "sgx".into(), vendor: "fortanix".into(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), - dynamic_linking: false, executables: true, linker_is_gnu: true, linker: Some("rust-lld".to_owned()), max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), llvm_args: vec!["--x86-experimental-lvi-inline-asm-hardening".into()], diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fuchsia.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fuchsia.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fuchsia.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_fuchsia.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::spec::{StackProbeType, Target}; +use crate::spec::{SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::fuchsia_base::opts(); @@ -6,6 +6,7 @@ base.max_atomic_width = Some(64); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = SanitizerSet::ADDRESS; Target { llvm_target: "x86_64-fuchsia".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_linux_android.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_linux_android.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_linux_android.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_linux_android.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,7 +6,7 @@ // https://developer.android.com/ndk/guides/abis.html#86-64 base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "x86-64".to_string(); - let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); gcc_pre_link_args.push("-m64".to_string()); // Use high-entropy 64 bit address space for ASLR gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::dragonfly_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,12 +1,13 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-freebsd".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,12 +1,14 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-linux-gnu".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string()); + 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; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,13 +1,15 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.static_position_independent_executables = true; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-linux-musl".to_string(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs 2021-06-17 03:53:51.000000000 +0000 @@ -11,7 +11,7 @@ "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" .to_string(); base.code_model = Some(CodeModel::Kernel); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); Target { // FIXME: Some dispute, the linux-on-clang folks think this should use diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::openbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::redox_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "x86-64".to_string(); - let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); gcc_pre_link_args.push("-m64".to_string()); // Use high-entropy 64 bit address space for ASLR gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs 2021-06-17 03:53:51.000000000 +0000 @@ -4,7 +4,7 @@ let mut base = super::vxworks_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.disable_redzone = true; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/chalk/db.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/chalk/db.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/chalk/db.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/chalk/db.rs 2021-06-17 03:53:51.000000000 +0000 @@ -735,11 +735,14 @@ .into(), ty::GenericParamDefKind::Lifetime => { - let br = ty::BoundRegion { kind: ty::BrAnon(substs.len() as u32) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(substs.len()), + kind: ty::BrAnon(substs.len() as u32), + }; tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into() } - ty::GenericParamDefKind::Const => tcx + ty::GenericParamDefKind::Const { .. } => tcx .mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), ty: tcx.type_of(param.def_id), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/chalk/lowering.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/chalk/lowering.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/chalk/lowering.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/chalk/lowering.rs 2021-06-17 03:53:51.000000000 +0000 @@ -434,17 +434,11 @@ ReEarlyBound(_) => { panic!("Should have already been substituted."); } - ReLateBound(db, br) => match br.kind { - ty::BoundRegionKind::BrAnon(var) => { - chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(db.as_u32()), - var as usize, - )) - .intern(interner) - } - ty::BoundRegionKind::BrNamed(_def_id, _name) => unimplemented!(), - ty::BrEnv => unimplemented!(), - }, + ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( + chalk_ir::DebruijnIndex::new(db.as_u32()), + br.var.as_usize(), + )) + .intern(interner), ReFree(_) => unimplemented!(), ReStatic => chalk_ir::LifetimeData::Static.intern(interner), ReVar(_) => unimplemented!(), @@ -467,7 +461,10 @@ let kind = match self.data(interner) { chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound( ty::DebruijnIndex::from_u32(var.debruijn.depth()), - ty::BoundRegion { kind: ty::BrAnon(var.index as u32) }, + ty::BoundRegion { + var: ty::BoundVar::from_usize(var.index), + kind: ty::BrAnon(var.index as u32), + }, ), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => { @@ -606,7 +603,7 @@ } impl<'tcx> LowerInto<'tcx, chalk_ir::Binders>>> - for &'tcx ty::List>> + for &'tcx ty::List>> { fn lower_into( self, @@ -677,7 +674,9 @@ } } -impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder> { +impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> + for ty::Binder<'tcx, ty::FnSig<'tcx>> +{ fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig> { chalk_ir::FnSig { abi: self.abi(), @@ -801,7 +800,7 @@ crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( interner: &RustInterner<'tcx>, tcx: TyCtxt<'tcx>, - ty: Binder, + ty: Binder<'tcx, T>, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); @@ -849,7 +848,10 @@ } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); @@ -895,7 +897,7 @@ }, }, - ty::BrEnv => unimplemented!(), + ty::BoundRegionKind::BrEnv => unimplemented!(), }, ty::ReEarlyBound(_re) => { @@ -931,7 +933,7 @@ self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -943,7 +945,7 @@ ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { - let new_br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)); } None => panic!("Missing `BrNamed`."), @@ -987,7 +989,7 @@ self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -1026,12 +1028,16 @@ // This covers any region variables in a goal, right? ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) { Some(idx) => { - let br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(*idx), + kind: ty::BrAnon(*idx), + }; self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } None => { let idx = self.named_regions.len() as u32; - let br = ty::BoundRegion { kind: ty::BrAnon(idx) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_traits/src/normalize_erasing_regions.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,24 +1,35 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable}; use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers) { - *p = Providers { normalize_generic_arg_after_erasing_regions, ..*p }; + *p = Providers { + normalize_generic_arg_after_erasing_regions: |tcx, goal| { + debug!("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) + }, + normalize_mir_const_after_erasing_regions: |tcx, goal| { + normalize_after_erasing_regions(tcx, goal) + }, + ..*p + }; } -fn normalize_generic_arg_after_erasing_regions<'tcx>( +#[instrument(level = "debug", skip(tcx))] +fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>, -) -> GenericArg<'tcx> { - debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); - + goal: ParamEnvAnd<'tcx, T>, +) -> T { let ParamEnvAnd { param_env, value } = goal; - tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).normalize(value) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -15,9 +15,10 @@ #![feature(box_patterns)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(control_flow_enum)] #![recursion_limit = "512"] // For rustdoc diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/opaque_types.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/opaque_types.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/opaque_types.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/opaque_types.rs 2021-06-17 03:53:51.000000000 +0000 @@ -697,7 +697,7 @@ { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { t.as_ref().skip_binder().visit_with(self); ControlFlow::CONTINUE @@ -1171,7 +1171,7 @@ // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(predicate); - let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); + let cause = traits::ObligationCause::new(span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/auto_trait.rs 2021-06-17 03:53:51.000000000 +0000 @@ -12,6 +12,7 @@ use std::collections::hash_map::Entry; use std::collections::VecDeque; +use std::iter; // FIXME(twk): this is obviously not nice to duplicate like that #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] @@ -83,7 +84,7 @@ let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) }; - let trait_pred = ty::Binder::bind(trait_ref); + let trait_pred = ty::Binder::dummy(trait_ref); let bail_out = tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::with_negative(&infcx, true); @@ -279,7 +280,7 @@ let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); - predicates.push_back(ty::Binder::bind(ty::TraitPredicate { + predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), @@ -428,7 +429,9 @@ return true; } - for (new_region, old_region) in new_substs.regions().zip(old_substs.regions()) { + for (new_region, old_region) in + iter::zip(new_substs.regions(), old_substs.regions()) + { match (new_region, old_region) { // If both predicates have an `ReLateBound` (a HRTB) in the // same spot, we do nothing. @@ -803,12 +806,10 @@ } ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match select.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty)), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/coherence.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/coherence.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/coherence.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/coherence.rs 2021-06-17 03:53:51.000000000 +0000 @@ -74,23 +74,22 @@ let impl2_ref = tcx.impl_trait_ref(impl2_def_id); // Check if any of the input types definitely do not unify. - if impl1_ref - .iter() - .flat_map(|tref| tref.substs.types()) - .zip(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); - 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() - } else { - // Types might unify - false - } - }) - { + if iter::zip( + impl1_ref.iter().flat_map(|tref| tref.substs.types()), + 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); + 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() + } else { + // Types might unify + false + } + }) { // Some types involved are definitely different, so the impls couldn't possibly overlap. debug!("overlapping_impls: fast_reject early-exit"); return no_overlap(); @@ -587,6 +586,11 @@ false } + ty::Closure(..) => { + // Similar to the `Opaque` case (#83613). + false + } + ty::Dynamic(ref tt, ..) => { if let Some(principal) = tt.principal() { def_id_is_local(principal.def_id(), in_crate) @@ -597,7 +601,7 @@ ty::Error(_) => true, - ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { + ty::Generator(..) | ty::GeneratorWitness(..) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs 2021-06-17 03:53:51.000000000 +0000 @@ -13,7 +13,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; -use rustc_middle::mir::abstract_const::{Node, NodeId}; +use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::subst::{Subst, SubstsRef}; @@ -23,6 +23,7 @@ use rustc_span::Span; use std::cmp; +use std::iter; use std::ops::ControlFlow; /// Check if a given constant can be evaluated. @@ -32,7 +33,7 @@ substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, -) -> Result<(), ErrorHandled> { +) -> Result<(), NotConstEvaluatable> { debug!("is_const_evaluatable({:?}, {:?})", def, substs); if infcx.tcx.features().const_evaluatable_checked { let tcx = infcx.tcx; @@ -103,29 +104,10 @@ match failure_kind { FailureKind::MentionsInfer => { - return Err(ErrorHandled::TooGeneric); + return Err(NotConstEvaluatable::MentionsInfer); } FailureKind::MentionsParam => { - // FIXME(const_evaluatable_checked): Better error message. - let mut err = - infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant"); - let const_span = tcx.def_span(def.did); - // FIXME(const_evaluatable_checked): Update this suggestion once - // explicit const evaluatable bounds are implemented. - if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span) - { - err.span_help( - tcx.def_span(def.did), - &format!("try adding a `where` bound using this expression: `where [u8; {}]: Sized`", snippet), - ); - } else { - err.span_help( - const_span, - "consider adding a `where` bound for this expression", - ); - } - err.emit(); - return Err(ErrorHandled::Reported(ErrorReported)); + return Err(NotConstEvaluatable::MentionsParam); } FailureKind::Concrete => { // Dealt with below by the same code which handles this @@ -163,7 +145,11 @@ // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); + let concrete = infcx.const_eval_resolve( + param_env, + ty::Unevaluated { def, substs, promoted: None }, + Some(span), + ); if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { @@ -180,34 +166,16 @@ debug!(?concrete, "is_const_evaluatable"); match concrete { - Err(ErrorHandled::TooGeneric) if !substs.has_infer_types_or_consts() => { - // FIXME(const_evaluatable_checked): We really should move - // emitting this error message to fulfill instead. For - // now this is easier. - // - // This is not a problem without `const_evaluatable_checked` as - // all `ConstEvaluatable` predicates have to be fulfilled for compilation - // to succeed. - // - // @lcnr: We already emit an error for things like - // `fn test() -> [0 - N]` eagerly here, - // so until we fix this I don't really care. - - let mut err = infcx - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - // - // Note that with `feature(const_evaluatable_checked)` this case should not - // be reachable. - err.note("this may fail depending on what value the parameter takes"); - err.emit(); - Err(ErrorHandled::Reported(ErrorReported)) + Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() { + true => NotConstEvaluatable::MentionsInfer, + false => NotConstEvaluatable::MentionsParam, + }), + Err(ErrorHandled::Linted) => { + infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); + Err(NotConstEvaluatable::Error(ErrorReported)) } - c => c.map(drop), + Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), + Ok(_) => Ok(()), } } @@ -239,7 +207,9 @@ ct: &ty::Const<'tcx>, ) -> Result>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(def, substs, None) => AbstractConst::new(tcx, def, substs), + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => { + AbstractConst::new(tcx, def, substs) + } ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } @@ -532,22 +502,25 @@ if let Some(next) = self.build_terminator(block.terminator())? { block = &self.body.basic_blocks()[next]; } else { - assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + break; + } + } + + assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + for n in self.nodes.iter() { + if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. - assert!(!self.nodes.iter().any(|n| matches!( - n.node, - Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ }) - ))); - - self.nodes[self.locals[mir::RETURN_PLACE]].used = true; - if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { - self.error(Some(unused.span), "dead code")?; - } - - return Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))); + assert_eq!(ct.promoted, None); } } + + self.nodes[self.locals[mir::RETURN_PLACE]].used = true; + if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { + self.error(Some(unused.span), "dead code")?; + } + + Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) } } @@ -673,10 +646,16 @@ // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This // means that we only allow inference variables if they are equal. (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) => a_def == b_def && a_substs == b_substs, + // We expand generic anonymous constants at the start of this function, so this + // branch should only be taking when dealing with associated constants, at + // which point directly comparing them seems like the desired behavior. + // + // FIXME(const_evaluatable_checked): This isn't actually the case. + // We also take this branch for concrete anonymous constants and + // expand generic anonymous constants with concrete substs. + (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => { + a_uv == b_uv + } // FIXME(const_evaluatable_checked): We may want to either actually try // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like // this, for now we just return false here. @@ -694,9 +673,7 @@ if a_args.len() == b_args.len() => { try_unify(tcx, a.subtree(a_f), b.subtree(b_f)) - && a_args - .iter() - .zip(b_args) + && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } _ => false, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -2,10 +2,10 @@ pub mod suggestions; use super::{ - ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, + OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, + SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -17,7 +17,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ @@ -28,6 +28,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; +use std::iter; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; @@ -161,7 +162,7 @@ } } - for (error, suppressed) in errors.iter().zip(is_suppressed) { + for (error, suppressed) in iter::zip(errors, is_suppressed) { if !suppressed { self.report_fulfillment_error(error, body_id, fallback_has_occurred); } @@ -502,14 +503,14 @@ let unit_obligation = obligation.with(predicate.without_const().to_predicate(tcx)); if self.predicate_may_hold(&unit_obligation) { + err.note("this trait is implemented for `()`."); err.note( - "the trait is implemented for `()`. \ - Possibly this error has been caused by changes to \ - Rust's type-inference algorithm (see issue #48950 \ - \ - for more information). Consider whether you meant to use \ - the type `()` here instead.", + "this error might have been caused by changes to \ + Rust's type-inference algorithm (see issue #48950 \ + \ + for more information).", ); + err.help("did you intend to use the type `()` here instead?"); } } @@ -738,24 +739,59 @@ let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } - ConstEvalFailure(ErrorHandled::TooGeneric) => { - bug!("too generic should have been handled in `is_const_evaluatable`"); + + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { + bug!( + "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" + ) + } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { + if !self.tcx.features().const_evaluatable_checked { + let mut err = self.tcx.sess.struct_span_err( + span, + "constant expression depends on a generic parameter", + ); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + // + // Note that with `feature(const_evaluatable_checked)` this case should not + // be reachable. + err.note("this may fail depending on what value the parameter takes"); + err.emit(); + return; + } + + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::ConstEvaluatable(def, _) => { + let mut err = + self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); + let const_span = self.tcx.def_span(def.did); + match self.tcx.sess.source_map().span_to_snippet(const_span) { + Ok(snippet) => err.help(&format!( + "try adding a `where` bound using this expression: `where [(); {}]:`", + snippet + )), + _ => err.help("consider adding a `where` bound using this expression"), + }; + err + } + _ => { + span_bug!( + span, + "unexpected non-ConstEvaluatable predicate, this should not be reachable" + ) + } + } } + // Already reported in the query. - ConstEvalFailure(ErrorHandled::Reported(ErrorReported)) => { + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorReported)) => { // FIXME(eddyb) remove this once `ErrorReported` becomes a proof token. self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error"); return; } - // Already reported in the query, but only as a lint. - // This shouldn't actually happen for constants used in types, modulo - // bugs. The `delay_span_bug` here ensures it won't be ignored. - ConstEvalFailure(ErrorHandled::Linted) => { - self.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); - return; - } - Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } @@ -1190,10 +1226,11 @@ ); let is_normalized_ty_expected = !matches!( - obligation.cause.code, + obligation.cause.code.peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ObjectCastObligation(_) + | ObligationCauseCode::OpaqueType ); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( @@ -1917,7 +1954,7 @@ Arg(String, String), /// An argument of tuple type. For a "found" argument, the span is - /// the locationo in the source of the pattern. For a "expected" + /// the location in the source of the pattern. For a "expected" /// argument, it will be None. The vector is a list of (name, ty) /// strings for the components of the tuple. Tuple(Option, Vec<(String, String)>), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs 2021-06-17 03:53:51.000000000 +0000 @@ -7,6 +7,7 @@ use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, GenericParamDefKind}; use rustc_span::symbol::sym; +use std::iter; use super::InferCtxtPrivExt; @@ -51,12 +52,11 @@ if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { self_match_impls.push(def_id); - if trait_ref - .substs - .types() - .skip(1) - .zip(impl_trait_ref.substs.types().skip(1)) - .all(|(u, v)| self.fuzzy_match_tys(u, v)) + if iter::zip( + trait_ref.substs.types().skip(1), + impl_trait_ref.substs.types().skip(1), + ) + .all(|(u, v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); } @@ -163,61 +163,65 @@ flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); } - let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); - // This is also included through the generics list as `Self`, - // but the parser won't allow you to use it - flags.push((sym::_Self, Some(self_ty.to_string()))); - if let Some(def) = self_ty.ty_adt_def() { - // We also want to be able to select self's original - // signature with no type arguments resolved - flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); - } - for param in generics.params.iter() { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => continue, - }; - let name = param.name; - flags.push((name, Some(value))); - } - - if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push((sym::crate_local, None)); - } - - // Allow targeting all integers using `{integral}`, even if the exact type was resolved - if self_ty.is_integral() { - flags.push((sym::_Self, Some("{integral}".to_owned()))); - } - - if let ty::Array(aty, len) = self_ty.kind() { - flags.push((sym::_Self, Some("[]".to_owned()))); - flags.push((sym::_Self, Some(format!("[{}]", aty)))); - if let Some(def) = aty.ty_adt_def() { - // We also want to be able to select the array's type's original + // Add all types without trimmed paths. + ty::print::with_no_trimmed_paths(|| { + let generics = self.tcx.generics_of(def_id); + let self_ty = trait_ref.self_ty(); + // This is also included through the generics list as `Self`, + // but the parser won't allow you to use it + flags.push((sym::_Self, Some(self_ty.to_string()))); + if let Some(def) = self_ty.ty_adt_def() { + // We also want to be able to select self's original // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did).to_string(); - flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); + } - let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); - let string = match len { - Some(n) => format!("[{}; {}]", type_string, n), - None => format!("[{}; _]", type_string), + for param in generics.params.iter() { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => continue, }; - flags.push((sym::_Self, Some(string))); + let name = param.name; + flags.push((name, Some(value))); } - } - if let ty::Dynamic(traits, _) = self_ty.kind() { - for t in traits.iter() { - if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { - flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + + if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { + flags.push((sym::crate_local, None)); + } + + // Allow targeting all integers using `{integral}`, even if the exact type was resolved + if self_ty.is_integral() { + flags.push((sym::_Self, Some("{integral}".to_owned()))); + } + + if let ty::Array(aty, len) = self_ty.kind() { + flags.push((sym::_Self, Some("[]".to_owned()))); + flags.push((sym::_Self, Some(format!("[{}]", aty)))); + if let Some(def) = aty.ty_adt_def() { + // We also want to be able to select the array's type's original + // signature with no type arguments resolved + let type_string = self.tcx.type_of(def.did).to_string(); + flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + + let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); + let string = match len { + Some(n) => format!("[{}; {}]", type_string, n), + None => format!("[{}; _]", type_string), + }; + flags.push((sym::_Self, Some(string))); } } - } + if let ty::Dynamic(traits, _) = self_ty.kind() { + for t in traits.iter() { + if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { + flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + } + } + } + }); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs 2021-06-17 03:53:51.000000000 +0000 @@ -28,6 +28,7 @@ use super::InferCtxtPrivExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_middle::ty::print::with_no_trimmed_paths; #[derive(Debug)] pub enum GeneratorInteriorOrUpvar { @@ -65,7 +66,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -73,7 +74,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool; @@ -82,14 +83,14 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -98,7 +99,7 @@ obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; @@ -108,7 +109,7 @@ err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool; fn point_at_returns_when_relevant( @@ -170,7 +171,7 @@ &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ); } @@ -440,7 +441,8 @@ { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = trait_ref.print_only_trait_path().to_string(); + let constraint = + with_no_trimmed_paths(|| trait_ref.print_only_trait_path().to_string()); if suggest_constraining_type_param( self.tcx, generics, @@ -583,7 +585,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let self_ty = match trait_ref.self_ty().no_bound_vars() { @@ -676,7 +678,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool { @@ -761,7 +763,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let span = obligation.cause.span; @@ -824,7 +826,7 @@ &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let span = obligation.cause.span; @@ -896,10 +898,10 @@ obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let is_empty_tuple = - |ty: ty::Binder>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); + |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); @@ -948,7 +950,7 @@ err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool { match obligation.cause.code.peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. @@ -1840,6 +1842,7 @@ | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::UnifyReceiver(..) + | ObligationCauseCode::OpaqueType | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); @@ -2067,7 +2070,14 @@ // Don't print the tuple of capture types if !is_upvar_tys_infer_tuple { - err.note(&format!("required because it appears within the type `{}`", ty)); + let msg = format!("required because it appears within the type `{}`", ty); + match ty.kind() { + ty::Adt(def, _) => match self.tcx.opt_item_name(def.did) { + Some(ident) => err.span_note(ident.span, &msg), + None => err.note(&msg), + }, + _ => err.note(&msg), + }; } obligated_types.push(ty); @@ -2089,11 +2099,36 @@ ObligationCauseCode::ImplDerivedObligation(ref data) => { let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); let parent_def_id = parent_trait_ref.def_id(); - err.note(&format!( + let msg = format!( "required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty() - )); + ); + let mut candidates = vec![]; + self.tcx.for_each_relevant_impl( + parent_def_id, + parent_trait_ref.self_ty().skip_binder(), + |impl_def_id| { + candidates.push(impl_def_id); + }, + ); + match &candidates[..] { + [def_id] => match self.tcx.hir().get_if_local(*def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) => { + let mut spans = Vec::with_capacity(2); + if let Some(trait_ref) = of_trait { + spans.push(trait_ref.path.span); + } + spans.push(self_ty.span); + err.span_note(spans, &msg) + } + _ => err.note(&msg), + }, + _ => err.note(&msg), + }; let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); let mut data = data; @@ -2144,19 +2179,60 @@ ) }); } - ObligationCauseCode::CompareImplMethodObligation { .. } => { - err.note(&format!( - "the requirement `{}` appears on the impl method but not on the corresponding \ - trait method", - predicate - )); + ObligationCauseCode::CompareImplMethodObligation { + item_name, + trait_item_def_id, + .. + } => { + let msg = format!( + "the requirement `{}` appears on the impl method `{}` but not on the \ + corresponding trait method", + predicate, item_name, + ); + let sp = self + .tcx + .opt_item_name(trait_item_def_id) + .map(|i| i.span) + .unwrap_or_else(|| self.tcx.def_span(trait_item_def_id)); + let mut assoc_span: MultiSpan = sp.into(); + assoc_span.push_span_label( + sp, + format!("this trait method doesn't have the requirement `{}`", predicate), + ); + if let Some(ident) = self + .tcx + .opt_associated_item(trait_item_def_id) + .and_then(|i| self.tcx.opt_item_name(i.container.id())) + { + assoc_span.push_span_label(ident.span, "in this trait".into()); + } + err.span_note(assoc_span, &msg); } - ObligationCauseCode::CompareImplTypeObligation { .. } => { - err.note(&format!( - "the requirement `{}` appears on the associated impl type but not on the \ + ObligationCauseCode::CompareImplTypeObligation { + item_name, trait_item_def_id, .. + } => { + let msg = format!( + "the requirement `{}` appears on the associated impl type `{}` but not on the \ corresponding associated trait type", - predicate - )); + predicate, item_name, + ); + let sp = self.tcx.def_span(trait_item_def_id); + let mut assoc_span: MultiSpan = sp.into(); + assoc_span.push_span_label( + sp, + format!( + "this trait associated type doesn't have the requirement `{}`", + predicate, + ), + ); + if let Some(ident) = self + .tcx + .opt_associated_item(trait_item_def_id) + .and_then(|i| self.tcx.opt_item_name(i.container.id())) + { + assoc_span.push_span_label(ident.span, "in this trait".into()); + } + err.span_note(assoc_span, &msg); } ObligationCauseCode::CompareImplConstObligation => { err.note(&format!( @@ -2190,7 +2266,7 @@ &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ) { debug!( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/fulfill.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,8 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_infer::traits::{TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::subst::SubstsRef; @@ -18,7 +19,7 @@ use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; -use super::{ConstEvalFailure, Unimplemented}; +use super::Unimplemented; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; @@ -498,14 +499,19 @@ obligation.cause.span, ) { Ok(()) => ProcessResult::Changed(vec![]), - Err(ErrorHandled::TooGeneric) => { + Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); ProcessResult::Unchanged } - Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), + Err( + e @ NotConstEvaluatable::MentionsParam + | e @ NotConstEvaluatable::Error(_), + ) => ProcessResult::Error(CodeSelectionError( + SelectionError::NotConstEvaluatable(e), + )), } } @@ -516,15 +522,13 @@ // if the constants depend on generic parameters. // // Let's just see where this breaks :shrug: - if let ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) = (c1.val, c2.val) + if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = + (c1.val, c2.val) { if self .selcx .tcx() - .try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + .try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs))) { return ProcessResult::Changed(vec![]); } @@ -534,18 +538,17 @@ let stalled_on = &mut pending_obligation.stalled_on; let mut evaluate = |c: &'tcx Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match self.selcx.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)), Err(ErrorHandled::TooGeneric) => { stalled_on.extend( - substs + unevaluated + .substs .iter() .filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); @@ -576,11 +579,11 @@ } } (Err(ErrorHandled::Reported(ErrorReported)), _) - | (_, Err(ErrorHandled::Reported(ErrorReported))) => { - ProcessResult::Error(CodeSelectionError(ConstEvalFailure( - ErrorHandled::Reported(ErrorReported), - ))) - } + | (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error( + CodeSelectionError(SelectionError::NotConstEvaluatable( + NotConstEvaluatable::Error(ErrorReported), + )), + ), (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { span_bug!( obligation.cause.span(self.selcx.tcx()), @@ -681,7 +684,7 @@ /// Returns the set of inference variables contained in `substs`. fn substs_infer_vars<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, - substs: ty::Binder>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> impl Iterator> { selcx .infcx() diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -483,7 +483,7 @@ let substs = trait_ref.map_bound(|trait_ref| { InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }) diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/object_safety.rs 2021-06-17 03:53:51.000000000 +0000 @@ -132,6 +132,14 @@ .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)), ); + violations.extend( + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) + .map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)), + ); + debug!( "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, violations @@ -439,8 +447,7 @@ return Some(MethodViolationCode::WhereClauseReferencesSelf); } - let receiver_ty = - tcx.liberate_late_bound_regions(method.def_id, sig.map_bound(|sig| sig.inputs()[0])); + let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0)); // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. @@ -757,7 +764,7 @@ struct IllegalSelfTypeVisitor<'tcx> { tcx: TyCtxt<'tcx>, trait_def_id: DefId, - supertraits: Option>>, + supertraits: Option>, } impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { @@ -778,8 +785,10 @@ // Compute supertraits of current trait lazily. if self.supertraits.is_none() { let trait_ref = - ty::Binder::bind(ty::TraitRef::identity(self.tcx, self.trait_def_id)); - self.supertraits = Some(traits::supertraits(self.tcx, trait_ref).collect()); + ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)); + self.supertraits = Some( + traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(), + ); } // Determine whether the trait reference `Foo as @@ -790,9 +799,11 @@ // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder::bind(data.trait_ref(self.tcx)); - let is_supertrait_of_current_trait = - self.supertraits.as_ref().unwrap().contains(&projection_trait_ref); + let is_supertrait_of_current_trait = self + .supertraits + .as_ref() + .unwrap() + .contains(&data.trait_ref(self.tcx).def_id); if is_supertrait_of_current_trait { ControlFlow::CONTINUE // do not walk contained types, do not report error, do collect $200 diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs 2021-06-17 03:53:51.000000000 +0000 @@ -337,7 +337,7 @@ .iter() .filter_map(|param| { let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize].to_string() } GenericParamDefKind::Lifetime => return None, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/project.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/project.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/project.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/project.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1275,6 +1275,9 @@ let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); + // We get here from `poly_project_and_unify_type` which replaces bound vars + // with placeholders + debug_assert!(!self_ty.has_escaping_bound_vars()); let substs = tcx.mk_substs([self_ty.into()].iter()); let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); @@ -1306,7 +1309,7 @@ ty: self_ty.ptr_metadata_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false) + confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -3,7 +3,7 @@ //! which makes a canonical query by replacing unbound inference //! variables and regions, so that results can be reused more broadly. //! The providers for the queries defined here can be found in -//! `librustc_traits`. +//! `rustc_traits`. pub mod dropck_outlives; pub mod evaluate_obligation; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/normalize.rs 2021-06-17 03:53:51.000000000 +0000 @@ -10,6 +10,7 @@ use rustc_data_structures::sso::SsoHashMap; 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::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -214,4 +215,8 @@ let constant = constant.super_fold_with(self); 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) + } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs 2021-06-17 03:53:51.000000000 +0000 @@ -8,12 +8,6 @@ pub ty: Ty<'tcx>, } -impl<'tcx> ImpliedOutlivesBounds<'tcx> { - pub fn new(ty: Ty<'tcx>) -> Self { - ImpliedOutlivesBounds { ty } - } -} - impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { type QueryResponse = Vec>; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/confirmation.rs 2021-06-17 03:53:51.000000000 +0000 @@ -272,7 +272,7 @@ &mut self, obligation: &TraitObligation<'tcx>, trait_def_id: DefId, - nested: ty::Binder>>, + nested: ty::Binder<'tcx, Vec>>, ) -> ImplSourceAutoImplData> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { @@ -462,12 +462,11 @@ for assoc_type in assoc_types { if !tcx.generics_of(assoc_type).params.is_empty() { - // FIXME(generic_associated_types) generate placeholders to - // extend the trait substs. - tcx.sess.span_fatal( + tcx.sess.delay_span_bug( obligation.cause.span, - "generic associated types in trait objects are not supported yet", + "GATs in trait object shouldn't have been considered", ); + return Err(SelectionError::Unimplemented); } // This maybe belongs in wf, but that can't (doesn't) handle // higher-ranked things. @@ -748,7 +747,7 @@ cause, obligation.recursion_depth + 1, obligation.param_env, - ty::Binder::bind(outlives).to_predicate(tcx), + obligation.predicate.rebind(outlives).to_predicate(tcx), )); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/select/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -34,6 +34,7 @@ use rustc_hir::Constness; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -203,7 +204,7 @@ /// When does the builtin impl for `T: Trait` apply? enum BuiltinImplConditions<'tcx> { /// The impl is conditional on `T1, T2, ...: Trait`. - Where(ty::Binder>>), + Where(ty::Binder<'tcx, Vec>>), /// There is no built-in impl. There may be some other /// candidate (a where-clause or user-defined impl). None, @@ -547,7 +548,8 @@ obligation.cause.span, ) { Ok(()) => Ok(EvaluatedToOk), - Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsParam) => Ok(EvaluatedToErr), Err(_) => Ok(EvaluatedToErr), } } @@ -556,13 +558,11 @@ debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { self.infcx .const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) .map(|val| ty::Const::from_value(self.tcx(), val, c.ty)) @@ -863,7 +863,7 @@ stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>, ) -> Result { - let result = self.evaluation_probe(|this| { + let mut result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { Ok(selection) => { @@ -876,6 +876,19 @@ Err(..) => Ok(EvaluatedToErr), } })?; + + // If we erased any lifetimes, then we want to use + // `EvaluatedToOkModuloRegions` instead of `EvaluatedToOk` + // as your final result. The result will be cached using + // the freshened trait predicate as a key, so we need + // our result to be correct by *any* choice of original lifetimes, + // not just the lifetime choice for this particular (non-erased) + // predicate. + // See issue #80691 + if stack.fresh_trait_ref.has_erased_regions() { + result = result.max(EvaluatedToOkModuloRegions); + } + debug!(?result); Ok(result) } @@ -931,7 +944,7 @@ /// subobligations without taking in a 'parent' depth, causing the /// generated subobligations to have a `recursion_depth` of `0`. /// - /// To ensure that obligation_depth never decreasees, we force all subobligations + /// To ensure that obligation_depth never decreases, we force all subobligations /// to have at least the depth of the original obligation. fn add_depth>>( &self, @@ -968,7 +981,7 @@ OP: FnOnce(&mut Self) -> R, { let (result, dep_node) = - self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self)); + self.tcx().dep_graph.with_anon_task(self.tcx(), DepKind::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } @@ -1348,7 +1361,17 @@ ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { - if other.value == victim.value && victim.constness == Constness::NotConst { + let value_same_except_bound_vars = other.value.skip_binder() + == victim.value.skip_binder() + && !other.value.skip_binder().has_escaping_bound_vars(); + if value_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 == Constness::NotConst { // Drop otherwise equivalent non-const candidates in favor of const candidates. true } else { @@ -1660,7 +1683,10 @@ /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` - fn constituent_types_for_ty(&self, t: ty::Binder>) -> ty::Binder>> { + fn constituent_types_for_ty( + &self, + t: ty::Binder<'tcx, Ty<'tcx>>, + ) -> ty::Binder<'tcx, Vec>> { match *t.skip_binder().kind() { ty::Uint(_) | ty::Int(_) @@ -1733,7 +1759,7 @@ cause: ObligationCause<'tcx>, recursion_depth: usize, trait_def_id: DefId, - types: ty::Binder>>, + types: ty::Binder<'tcx, Vec>>, ) -> Vec> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound @@ -1754,7 +1780,7 @@ .skip_binder() // binder moved -\ .iter() .flat_map(|ty| { - let ty: ty::Binder> = types.rebind(ty); // <----/ + let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(ty); // <----/ self.infcx.commit_unconditionally(|_| { let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty); @@ -1874,7 +1900,7 @@ // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.skip_binder().trait_ref.substs.iter().zip(impl_trait_ref.substs).any( + iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any( |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/specialize/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -395,14 +395,14 @@ // that's passed in. let decorate = |err: LintDiagnosticBuilder<'_>| { let msg = format!( - "conflicting implementations of trait `{}`{}:{}", + "conflicting implementations of trait `{}`{}{}", overlap.trait_desc, overlap .self_desc .clone() .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }), match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", + Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)", _ => "", } ); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/util.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/util.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/util.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/util.rs 2021-06-17 03:53:51.000000000 +0000 @@ -328,7 +328,7 @@ self_ty: Ty<'tcx>, sig: ty::PolyFnSig<'tcx>, tuple_arguments: TupleArgumentsFlag, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), @@ -346,7 +346,7 @@ fn_trait_def_id: DefId, self_ty: Ty<'tcx>, sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { debug_assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/wf.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/wf.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/wf.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_trait_selection/src/traits/wf.rs 2021-06-17 03:53:51.000000000 +0000 @@ -430,7 +430,7 @@ GenericArgKind::Const(constant) => { match constant.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { assert!(promoted.is_none()); let obligations = self.nominal_obligations(def.did, substs); @@ -692,11 +692,7 @@ let predicates = predicates.instantiate(self.infcx.tcx, substs); debug_assert_eq!(predicates.predicates.len(), origins.len()); - predicates - .predicates - .into_iter() - .zip(predicates.spans.into_iter()) - .zip(origins.into_iter().rev()) + iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev()) .map(|((pred, span), origin_def_id)| { let cause = self.cause(traits::BindingObligation(origin_def_id, span)); traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) @@ -708,7 +704,7 @@ fn from_object_ty( &mut self, ty: Ty<'tcx>, - data: &'tcx ty::List>>, + data: &'tcx ty::List>>, region: ty::Region<'tcx>, ) { // Imagine a type like this: @@ -771,7 +767,7 @@ /// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Vec> { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/Cargo.toml rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/Cargo.toml --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/Cargo.toml 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/Cargo.toml 2021-06-17 03:53:51.000000000 +0000 @@ -26,3 +26,4 @@ rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_ty_utils = { path = "../rustc_ty_utils" } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/errors.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/errors.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/errors.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/errors.rs 2021-06-17 03:53:51.000000000 +0000 @@ -10,6 +10,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::collections::BTreeSet; +use std::iter; impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using @@ -309,7 +310,7 @@ // that the user forgot to give the associtated type's name. The canonical // example would be trying to use `Iterator` instead of // `Iterator`. - for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) { + for (potential, item) in iter::zip(&potential_assoc_types, assoc_items) { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) { suggestions.push((*potential, format!("{} = {}", item.ident, snippet))); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/generics.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/generics.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/generics.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/generics.rs 2021-06-17 03:53:51.000000000 +0000 @@ -64,7 +64,7 @@ kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => match path.res { Res::Err => { add_braces_suggestion(arg, &mut err); @@ -82,7 +82,7 @@ if param_type.is_suggestable() { err.span_suggestion( tcx.def_span(src_def_id), - "consider changing this type paramater to a `const`-generic", + "consider changing this type parameter to be a `const` generic", format!("const {}: {}", param_name, param_type), Applicability::MaybeIncorrect, ); @@ -93,7 +93,7 @@ }, ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => add_braces_suggestion(arg, &mut err), ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), @@ -109,6 +109,20 @@ ); } } + (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { + let body = tcx.hir().body(cnst.value.body); + if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = + body.value.kind + { + if let Res::Def(DefKind::Fn { .. }, id) = path.res { + err.help(&format!( + "`{}` is a function item, not a type", + tcx.item_name(id) + )); + err.help("function item types cannot be named directly"); + } + } + } _ => {} } @@ -166,7 +180,7 @@ parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, - arg_count: GenericArgCountResult, + arg_count: &GenericArgCountResult, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ) -> SubstsRef<'tcx> { // Collect the segments of the path; we need to substitute arguments @@ -236,7 +250,7 @@ match (arg, ¶m.kind, arg_count.explicit_late_bound) { (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) - | (GenericArg::Const(_), GenericParamDefKind::Const, _) => { + | (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => { substs.push(ctx.provided_kind(param, arg)); args.next(); params.next(); @@ -282,11 +296,11 @@ GenericParamDefKind::Type { .. } => { ParamKindOrd::Type } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { ParamKindOrd::Const { unordered: tcx .features() - .const_generics, + .unordered_const_ty_params(), } } }, @@ -309,7 +323,9 @@ GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx.features().const_generics, + unordered: tcx + .features() + .unordered_const_ty_params(), }, }), Some(&format!( @@ -499,7 +515,9 @@ let expected_min = if infer_args { 0 } else { - param_counts.consts + named_type_param_count - default_counts.types + param_counts.consts + named_type_param_count + - default_counts.types + - default_counts.consts }; check_generics( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/astconv/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/astconv/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -198,6 +198,7 @@ } impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + #[tracing::instrument(level = "debug", skip(self))] pub fn ast_region_to_region( &self, lifetime: &hir::Lifetime, @@ -209,14 +210,20 @@ let r = match tcx.named_region(lifetime.hir_id) { Some(rl::Region::Static) => tcx.lifetimes.re_static, - Some(rl::Region::LateBound(debruijn, id, _)) => { - let name = lifetime_name(id.expect_local()); - let br = ty::BoundRegion { kind: ty::BrNamed(id, name) }; + Some(rl::Region::LateBound(debruijn, index, def_id, _)) => { + let name = lifetime_name(def_id.expect_local()); + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrNamed(def_id, name), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } - Some(rl::Region::LateBoundAnon(debruijn, index)) => { - let br = ty::BoundRegion { kind: ty::BrAnon(index) }; + Some(rl::Region::LateBoundAnon(debruijn, index, anon_index)) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrAnon(anon_index), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } @@ -237,6 +244,8 @@ None => { self.re_infer(def, lifetime.span).unwrap_or_else(|| { + debug!(?lifetime, "unelided lifetime in signature"); + // This indicates an illegal lifetime // elision. `resolve_lifetime` should have // reported an error in this case -- but if @@ -263,7 +272,7 @@ def_id: DefId, item_segment: &hir::PathSegment<'_>, ) -> SubstsRef<'tcx> { - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -272,6 +281,7 @@ item_segment.infer_args, None, ); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -311,6 +321,7 @@ /// `[Vec, u8]` and `generic_args` are the arguments for the associated /// type itself: `['a]`. The returned `SubstsRef` concatenates these two /// lists: `[Vec, u8, 'a]`. + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_path<'a>( &self, span: Span, @@ -320,15 +331,10 @@ generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - debug!( - "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - generic_args={:?})", - def_id, self_ty, generic_args - ); let tcx = self.tcx(); let generics = tcx.generics_of(def_id); @@ -364,7 +370,7 @@ // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.len() == 0 { - return (tcx.intern_substs(&[]), vec![], arg_count); + return (tcx.intern_substs(&[]), arg_count); } let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self); @@ -443,7 +449,7 @@ self.astconv.ast_ty_to_ty(&ty).into() } } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { ty::Const::from_opt_const_arg_anon_const( tcx, ty::WithOptConstParam { @@ -504,15 +510,19 @@ tcx.ty_error().into() } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); - // FIXME(const_generics_defaults) - if infer_args { - // No const parameters were provided, we can infer all. - self.astconv.ct_infer(ty, Some(param), self.span).into() + if !infer_args && has_default { + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { - // We've already errored above about the mismatch. - tcx.const_error(ty).into() + if infer_args { + self.astconv.ct_infer(ty, Some(param), self.span).into() + } else { + // We've already errored above about the mismatch. + tcx.const_error(ty).into() + } } } } @@ -535,7 +545,7 @@ parent_substs, self_ty.is_some(), self_ty, - arg_count.clone(), + &arg_count, &mut substs_ctx, ); @@ -546,6 +556,18 @@ generic_args.args.is_empty(), ); + debug!( + "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", + generics, self_ty, substs + ); + + (substs, arg_count) + } + + fn create_assoc_bindings_for_generic_args<'a>( + &self, + generic_args: &'a hir::GenericArgs<'_>, + ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: // @@ -576,12 +598,7 @@ }) .collect(); - debug!( - "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", - generics, self_ty, substs - ); - - (substs, assoc_bindings, arg_count) + assoc_bindings } crate fn create_substs_for_associated_item( @@ -631,8 +648,27 @@ ) } - /// The given trait-ref must actually be a trait. - pub(super) fn instantiate_poly_trait_ref_inner( + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct + /// a full trait reference. The resulting trait reference is returned. This may also generate + /// auxiliary bounds, which are added to `bounds`. + /// + /// Example: + /// + /// ``` + /// poly_trait_ref = Iterator + /// self_ty = Foo + /// ``` + /// + /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. + /// + /// **A note on binders:** against our usual convention, there is an implied bounder around + /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. + /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` + /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be + /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, + /// however. + #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))] + pub fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, span: Span, @@ -643,18 +679,25 @@ ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); - debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); - self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); - let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref( + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); + debug!(?bound_vars); + + let (substs, arg_count) = self.create_substs_for_ast_trait_ref( trait_ref.path.span, trait_def_id, self_ty, trait_ref.path.segments.last().unwrap(), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self + .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args()); + + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); + debug!(?poly_trait_ref, ?assoc_bindings); bounds.trait_bounds.push((poly_trait_ref, span, constness)); let mut dup_bindings = FxHashMap::default(); @@ -672,50 +715,9 @@ // Okay to ignore `Err` because of `ErrorReported` (see above). } - debug!( - "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", - trait_ref, bounds, poly_trait_ref - ); - arg_count } - /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct - /// a full trait reference. The resulting trait reference is returned. This may also generate - /// auxiliary bounds, which are added to `bounds`. - /// - /// Example: - /// - /// ``` - /// poly_trait_ref = Iterator - /// self_ty = Foo - /// ``` - /// - /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. - /// - /// **A note on binders:** against our usual convention, there is an implied bounder around - /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. - /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` - /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be - /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, - /// however. - pub fn instantiate_poly_trait_ref( - &self, - poly_trait_ref: &hir::PolyTraitRef<'_>, - constness: Constness, - self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, - ) -> GenericArgCountResult { - self.instantiate_poly_trait_ref_inner( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - self_ty, - bounds, - false, - ) - } - pub fn instantiate_lang_item_trait_ref( &self, lang_item: hir::LangItem, @@ -727,7 +729,7 @@ ) { let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, trait_def_id, &[], @@ -736,7 +738,11 @@ false, Some(self_ty), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst)); let mut dup_bindings = FxHashMap::default(); @@ -760,23 +766,23 @@ self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, ) -> ty::TraitRef<'tcx> { - let (substs, assoc_bindings, _) = + let (substs, _) = self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); } ty::TraitRef::new(trait_def_id, substs) } + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_trait_ref<'a>( &self, span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { - debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); - + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); self.create_substs_for_ast_path( @@ -798,7 +804,7 @@ } // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool { + pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { let tcx = self.tcx(); // Try to find an unbound in bounds. @@ -853,29 +859,46 @@ /// **A note on binders:** there is an implied binder around /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. + #[tracing::instrument(level = "debug", skip(self, bounds))] fn add_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], bounds: &mut Bounds<'tcx>, + bound_vars: &'tcx ty::List, ) { let constness = self.default_constness_for_trait_bounds(); for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - self.instantiate_poly_trait_ref(b, constness, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + constness, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { - self.instantiate_poly_trait_ref(b, Constness::NotConst, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + Constness::NotConst, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self .instantiate_lang_item_trait_ref( - *lang_item, *span, *hir_id, args, param_ty, bounds, + lang_item, span, hir_id, args, param_ty, bounds, ), - hir::GenericBound::Outlives(ref l) => bounds - .region_bounds - .push((ty::Binder::bind(self.ast_region_to_region(l, None)), l.span)), + hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( + ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars), + l.span, + )), } } } @@ -903,7 +926,6 @@ sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) } @@ -923,7 +945,7 @@ if let Some(trait_ref) = ast_bound.trait_ref() { if let Some(trait_did) = trait_ref.trait_def_id() { if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound); + result.push(ast_bound.clone()); } } } @@ -935,13 +957,13 @@ fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds, &mut bounds); + self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty()); bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } @@ -958,6 +980,10 @@ /// **A note on binders:** given something like `T: for<'a> Iterator`, the /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + #[tracing::instrument( + level = "debug", + skip(self, bounds, speculative, dup_bindings, path_span) + )] fn add_predicates_for_ast_type_binding( &self, hir_ref_id: hir::HirId, @@ -984,7 +1010,6 @@ // // We want to produce `>::T == foo`. - debug!(?hir_ref_id, ?trait_ref, ?binding, ?bounds, "add_predicates_for_ast_type_binding",); let tcx = self.tcx(); let candidate = @@ -1085,7 +1110,7 @@ let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); debug!("late_bound_in_ty = {:?}", late_bound_in_ty); @@ -1134,10 +1159,8 @@ // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = - tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs); - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); - self.add_bounds(param_ty, &ast_bounds, bounds); + let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder())); + self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars()); } } Ok(()) @@ -1171,10 +1194,12 @@ Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), .. } = self.instantiate_poly_trait_ref( - trait_bound, + &trait_bound.trait_ref, + trait_bound.span, Constness::NotConst, dummy_self, &mut bounds, + false, ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -1659,7 +1684,7 @@ }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::bind(trait_ref)), + || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)), || "Self".to_string(), assoc_ident, span, @@ -2171,9 +2196,8 @@ /// 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> { - debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind); - let tcx = self.tcx(); let result_ty = match ast_ty.kind { @@ -2183,7 +2207,7 @@ } hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); - debug!("ast_ty_to_ty: r={:?}", r); + debug!(?r); let t = self.ast_ty_to_ty_inner(&mt.ty, true); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } @@ -2195,6 +2219,7 @@ require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); tcx.mk_fn_ptr(self.ty_of_fn( + ast_ty.hir_id, bf.unsafety, bf.abi, &bf.decl, @@ -2207,7 +2232,7 @@ self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { - debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); + debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); self.res_to_ty(opt_self_ty, path, false) } @@ -2223,7 +2248,7 @@ } } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { - debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment); + debug!(?qself, ?segment); let ty = self.ast_ty_to_ty(qself); let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind { @@ -2237,7 +2262,7 @@ } 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( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -2254,9 +2279,9 @@ let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } - hir::TyKind::Typeof(ref _e) => { + hir::TyKind::Typeof(ref e) => { tcx.sess.emit_err(TypeofReservedKeywordUsed { span: ast_ty.span }); - tcx.ty_error() + tcx.type_of(tcx.hir().local_def_id(e.hir_id)) } hir::TyKind::Infer => { // Infer also appears as the type of arguments or return @@ -2268,13 +2293,13 @@ hir::TyKind::Err => tcx.ty_error(), }; - debug!("ast_ty_to_ty: result_ty={:?}", result_ty); + debug!(?result_ty); self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); result_ty } - pub fn impl_trait_ty_to_ty( + fn impl_trait_ty_to_ty( &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], @@ -2335,6 +2360,7 @@ pub fn ty_of_fn( &self, + hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, @@ -2345,6 +2371,8 @@ debug!("ty_of_fn"); let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. let mut visitor = PlaceholderHirTyCollector::default(); @@ -2364,8 +2392,8 @@ debug!("ty_of_fn: output_ty={:?}", output_ty); - let bare_fn_ty = - ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); + let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); + let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); if !self.allow_ty_infer() { // We always collect the spans for placeholder types when evaluating `fn`s, but we @@ -2446,7 +2474,7 @@ fn compute_object_lifetime_bound( &self, span: Span, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Option> // if None, use the default { let tcx = self.tcx(); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/bounds.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/bounds.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/bounds.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/bounds.rs 2021-06-17 03:53:51.000000000 +0000 @@ -26,7 +26,7 @@ /// A list of region bounds on the (implicit) self type. So if you /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but /// the `T` is not explicitly included). - pub region_bounds: Vec<(ty::Binder>, Span)>, + pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. @@ -57,7 +57,7 @@ // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { - let trait_ref = ty::Binder::bind(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), }); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/callee.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/callee.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/callee.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/callee.rs 2021-06-17 03:53:51.000000000 +0000 @@ -17,6 +17,7 @@ use rustc_span::Span; use rustc_target::spec::abi; use rustc_trait_selection::autoderef::Autoderef; +use std::iter; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -539,7 +540,7 @@ debug!("attempt_resolution: method_callee={:?}", method_callee); for (method_arg_ty, self_arg_ty) in - method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) + iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) { fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/cast.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/cast.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/cast.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/cast.rs 2021-06-17 03:53:51.000000000 +0000 @@ -359,6 +359,21 @@ { sugg = Some(format!("&{}", mutbl.prefix_str())); } + } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() { + if fcx + .try_coerce( + self.expr, + fcx.tcx.mk_ref( + &ty::RegionKind::ReErased, + TypeAndMut { ty: self.expr_ty, mutbl }, + ), + self.cast_ty, + AllowTwoPhase::No, + ) + .is_ok() + { + sugg = Some(format!("&{}", mutbl.prefix_str())); + } } if let Some(sugg) = sugg { err.span_label(self.span, "invalid cast"); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/check.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/check.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/check.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/check.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,7 +6,7 @@ use rustc_attr as attr; use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; @@ -15,17 +15,18 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::util::{Discr, IntTypeExt, Representability}; -use rustc_middle::ty::{self, ParamEnv, RegionKind, ToPredicate, Ty, TyCtxt}; -use rustc_session::config::EntryFnType; +use rustc_middle::ty::util::{Discr, IntTypeExt}; +use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt}; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::opaque_types::InferCtxtExt as _; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCauseCode}; +use rustc_ty_utils::representability::{self, Representability}; +use std::iter; use std::ops::ControlFlow; pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -324,29 +325,6 @@ } fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); - // Check that the main return type implements the termination trait. - if let Some(term_id) = tcx.lang_items().termination() { - if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) { - let main_id = hir.local_def_id_to_hir_id(def_id); - if main_id == fn_id { - let substs = tcx.mk_substs_trait(declared_ret_ty, &[]); - let trait_ref = ty::TraitRef::new(term_id, substs); - let return_ty_span = decl.output.span(); - let cause = traits::ObligationCause::new( - return_ty_span, - fn_id, - ObligationCauseCode::MainFunctionType, - ); - - inherited.register_predicate(traits::Obligation::new( - cause, - param_env, - trait_ref.without_const().to_predicate(tcx), - )); - } - } - } - // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` if let Some(panic_impl_did) = tcx.lang_items().panic_impl() { if panic_impl_did == hir.local_def_id(fn_id).to_def_id() { @@ -1187,7 +1165,7 @@ // recursive type. It is only necessary to throw an error on those that // contain themselves. For case 2, there must be an inner type that will be // caught by case 1. - match rty.is_representable(tcx, sp) { + match representability::ty_is_representable(tcx, rty, sp) { Representability::SelfRecursive(spans) => { recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans); return false; @@ -1472,7 +1450,7 @@ } let mut disr_vals: Vec> = Vec::with_capacity(vs.len()); - for ((_, discr), v) in def.discriminants(tcx).zip(vs) { + for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) { // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { let variant_did = def.variants[VariantIdx::new(i)].def_id; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/closure.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/closure.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/closure.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/closure.rs 2021-06-17 03:53:51.000000000 +0000 @@ -69,7 +69,7 @@ let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); let ClosureSignatures { bound_sig, liberated_sig } = - self.sig_of_closure(expr_def_id.to_def_id(), decl, body, expected_sig); + self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig); debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); @@ -288,15 +288,16 @@ fn sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { if let Some(e) = expected_sig { - self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) + self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e) } else { - self.sig_of_closure_no_expectation(expr_def_id, decl, body) + self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body) } } @@ -304,13 +305,14 @@ /// types that the user gave into a signature. fn sig_of_closure_no_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { debug!("sig_of_closure_no_expectation()"); - let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); self.closure_sigs(expr_def_id, body, bound_sig) } @@ -364,6 +366,7 @@ /// regions with depth 1, which are bound then by the closure. fn sig_of_closure_with_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -375,7 +378,7 @@ // expectation if things don't see to match up with what we // expect. if expected_sig.sig.c_variadic() != decl.c_variadic { - return self.sig_of_closure_no_expectation(expr_def_id, decl, body); + return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body); } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { return self.sig_of_closure_with_mismatched_number_of_arguments( expr_def_id, @@ -411,9 +414,15 @@ // Along the way, it also writes out entries for types that the user // wrote into our typeck results, which are then later used by the privacy // check. - match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { + match self.check_supplied_sig_against_expectation( + hir_id, + expr_def_id, + decl, + body, + &closure_sigs, + ) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), - Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), + Err(_) => return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), } closure_sigs @@ -460,6 +469,7 @@ /// strategy. fn check_supplied_sig_against_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -469,7 +479,7 @@ // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) - let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); @@ -492,13 +502,13 @@ // The liberated version of this signature should be a subtype // of the liberated form of the expectation. - for ((hir_ty, &supplied_ty), expected_ty) in decl - .inputs - .iter() - .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below - .zip(expected_sigs.liberated_sig.inputs()) - // `liberated_sig` is E'. - { + for ((hir_ty, &supplied_ty), expected_ty) in iter::zip( + iter::zip( + decl.inputs, + supplied_sig.inputs().skip_binder(), // binder moved to (*) below + ), + expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. + ) { // Instantiate (this part of..) S to S', i.e., with fresh variables. let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( hir_ty.span, @@ -534,6 +544,7 @@ /// Also, record this closure signature for later. fn supplied_sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -545,6 +556,8 @@ decl, body.generator_kind, ); + let bound_vars = self.tcx.late_bound_vars(hir_id); + // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { @@ -571,13 +584,16 @@ }, }; - let result = ty::Binder::bind(self.tcx.mk_fn_sig( - supplied_arguments, - supplied_return, - decl.c_variadic, - hir::Unsafety::Normal, - Abi::RustCall, - )); + let result = ty::Binder::bind_with_vars( + self.tcx.mk_fn_sig( + supplied_arguments, + supplied_return, + decl.c_variadic, + hir::Unsafety::Normal, + Abi::RustCall, + ), + bound_vars, + ); debug!("supplied_sig_of_closure: result={:?}", result); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/coercion.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/coercion.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/coercion.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/coercion.rs 2021-06-17 03:53:51.000000000 +0000 @@ -973,6 +973,14 @@ } }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { + // Intrinsics are not coercible to function pointers. + if a_sig.abi() == Abi::RustIntrinsic + || a_sig.abi() == Abi::PlatformIntrinsic + || b_sig.abi() == Abi::RustIntrinsic + || b_sig.abi() == Abi::PlatformIntrinsic + { + return Err(TypeError::IntrinsicCast); + } // The signature must match. let a_sig = self.normalize_associated_types_in(new.span, a_sig); let b_sig = self.normalize_associated_types_in(new.span, b_sig); @@ -1440,9 +1448,8 @@ // as prior return coercions would not be relevant (#57664). let parent_id = fcx.tcx.hir().get_parent_node(id); let fn_decl = if let Some((expr, blk_id)) = expression { - pointing_at_return_type = fcx.suggest_mismatched_types_on_tail( - &mut err, expr, expected, found, cause.span, blk_id, - ); + pointing_at_return_type = + fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id); let parent = fcx.tcx.hir().get(parent_id); if let (Some(cond_expr), true, false) = ( fcx.tcx.hir().get_if_cause(expr.hir_id), @@ -1487,34 +1494,14 @@ if let (Some((expr, _)), Some((fn_decl, _, _))) = (expression, fcx.get_node_fn_decl(parent_item)) { - fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found); + fcx.suggest_missing_break_or_return_expr( + &mut err, expr, fn_decl, expected, found, id, parent_id, + ); } if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) { self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output); } - - if let Some(sp) = fcx.ret_coercion_span.get() { - // If the closure has an explicit return type annotation, - // then a type error may occur at the first return expression we - // see in the closure (if it conflicts with the declared - // return type). Skip adding a note in this case, since it - // would be incorrect. - if !err.span.primary_spans().iter().any(|&span| span == sp) { - let hir = fcx.tcx.hir(); - let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id)); - if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { - err.span_note( - sp, - &format!( - "return type inferred to be `{}` here", - fcx.resolve_vars_if_possible(expected) - ), - ); - } - } - } - err } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/compare_method.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/compare_method.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/compare_method.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/compare_method.rs 2021-06-17 03:53:51.000000000 +0000 @@ -14,6 +14,7 @@ use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; +use std::iter; use super::{potentially_plural_count, FnCtxt, Inherited}; @@ -224,7 +225,7 @@ let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, - ty::Binder::bind(impl_m_own_bounds.predicates), + ty::Binder::bind(impl_m_own_bounds.predicates, tcx), ); for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, obligations } = @@ -257,14 +258,14 @@ ); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -277,9 +278,8 @@ if let Err(terr) = sub_result { debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); - let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting( - &infcx, param_env, &terr, &cause, impl_m, impl_sig, trait_m, trait_sig, - ); + 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; @@ -290,18 +290,79 @@ "method `{}` has an incompatible type for trait", trait_m.ident ); - if let TypeError::Mutability = terr { - if let Some(trait_err_span) = trait_err_span { - if let Ok(trait_err_str) = tcx.sess.source_map().span_to_snippet(trait_err_span) + match &terr { + TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) + if trait_m.fn_has_self_parameter => + { + let ty = trait_sig.inputs()[0]; + let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { + ExplicitSelf::ByValue => "self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Mut) => { + "&mut self".to_owned() + } + _ => format!("self: {}", ty), + }; + + // When the `impl` receiver is an arbitrary self type, like `self: Box`, 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 { + ImplItemKind::Fn(ref sig, body) => tcx + .hir() + .body_param_names(body) + .zip(sig.decl.inputs.iter()) + .map(|(param, ty)| param.span.to(ty.span)) + .next() + .unwrap_or(impl_err_span), + _ => bug!("{:?} is not a method", impl_m), + }; + + diag.span_suggestion( + span, + "change the self-receiver type to match the trait", + sugg, + Applicability::MachineApplicable, + ); + } + TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { + if trait_sig.inputs().len() == *i { + // Suggestion to change output type. We do not suggest in `async` functions + // to avoid complex logic or incorrect output. + 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 { + ImplItemKind::Fn(ref sig, _) + if sig.header.asyncness == hir::IsAsync::NotAsync => + { + let msg = "change the output type to match the trait"; + let ap = Applicability::MachineApplicable; + match sig.decl.output { + hir::FnRetTy::DefaultReturn(sp) => { + let sugg = format!("-> {} ", trait_sig.output()); + diag.span_suggestion_verbose(sp, msg, sugg, ap); + } + hir::FnRetTy::Return(hir_ty) => { + let sugg = trait_sig.output().to_string(); + diag.span_suggestion(hir_ty.span, msg, sugg, ap); + } + }; + } + _ => {} + }; + } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { diag.span_suggestion( impl_err_span, - "consider changing the mutability to match the trait", - trait_err_str, + "change the parameter type to match the trait", + trait_ty.to_string(), Applicability::MachineApplicable, ); } } + _ => {} } infcx.note_type_err( @@ -384,90 +445,35 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( infcx: &infer::InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, terr: &TypeError<'_>, cause: &ObligationCause<'tcx>, impl_m: &ty::AssocItem, - impl_sig: ty::FnSig<'tcx>, trait_m: &ty::AssocItem, - trait_sig: ty::FnSig<'tcx>, ) -> (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 (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Fn(ref impl_m_sig, _) => { - (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) + let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).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), }; - - match *terr { - TypeError::Mutability => { - if let Some(def_id) = trait_m.def_id.as_local() { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(), - _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - }; - - impl_m_iter - .zip(trait_m_iter) - .find(|&(ref impl_arg, ref trait_arg)| { - match (&impl_arg.kind, &trait_arg.kind) { - ( - &hir::TyKind::Rptr(_, ref impl_mt), - &hir::TyKind::Rptr(_, ref trait_mt), - ) - | (&hir::TyKind::Ptr(ref impl_mt), &hir::TyKind::Ptr(ref trait_mt)) => { - impl_mt.mutbl != trait_mt.mutbl - } - _ => false, - } - }) - .map(|(ref impl_arg, ref trait_arg)| (impl_arg.span, Some(trait_arg.span))) - .unwrap_or_else(|| (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id))) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) + 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 { + 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), } - TypeError::Sorts(ExpectedFound { .. }) => { - if let Some(def_id) = trait_m.def_id.as_local() { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let (trait_m_output, trait_m_iter) = - match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Fn(ref trait_m_sig, _) => { - (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()) - } - _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - }; + }); - let impl_iter = impl_sig.inputs().iter(); - let trait_iter = trait_sig.inputs().iter(); - impl_iter - .zip(trait_iter) - .zip(impl_m_iter) - .zip(trait_m_iter) - .find_map(|(((&impl_arg_ty, &trait_arg_ty), impl_arg), trait_arg)| match infcx - .at(&cause, param_env) - .sub(trait_arg_ty, impl_arg_ty) - { - Ok(_) => None, - Err(_) => Some((impl_arg.span, Some(trait_arg.span))), - }) - .unwrap_or_else(|| { - if infcx - .at(&cause, param_env) - .sup(trait_sig.output(), impl_sig.output()) - .is_err() - { - (impl_m_output.span(), Some(trait_m_output.span())) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) - } - }) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) - } + match *terr { + TypeError::ArgumentMutability(i) => { + (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) + } + TypeError::ArgumentSorts(ExpectedFound { .. }, i) => { + (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) } _ => (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)), } @@ -517,8 +523,7 @@ tcx.sess, impl_m_span, E0185, - "method `{}` has a `{}` declaration in the impl, but \ - not in the trait", + "method `{}` has a `{}` declaration in the impl, but not in the trait", trait_m.ident, self_descr ); @@ -538,8 +543,7 @@ tcx.sess, impl_m_span, E0186, - "method `{}` has a `{}` declaration in the trait, but \ - not in the impl", + "method `{}` has a `{}` declaration in the trait, but not in the impl", trait_m.ident, self_descr ); @@ -792,14 +796,14 @@ let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in - impl_m_type_params.zip(trait_m_type_params) + iter::zip(impl_m_type_params, trait_m_type_params) { if impl_synthetic != trait_synthetic { let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local()); @@ -996,8 +1000,7 @@ tcx.sess, cause.span, E0326, - "implemented const `{}` has an incompatible type for \ - trait", + "implemented const `{}` has an incompatible type for trait", trait_c.ident ); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/demand.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/demand.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/demand.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/demand.rs 2021-06-17 03:53:51.000000000 +0000 @@ -37,6 +37,7 @@ self.suggest_missing_parentheses(err, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); + self.report_closure_infered_return_type(err, expected) } // Requires that the two types unify, and prints an error message if @@ -366,6 +367,29 @@ false } + /// If the given `HirId` corresponds to a block with a trailing expression, return that expression + crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> { + match self.tcx.hir().find(hir_id)? { + Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr, + _ => None, + } + } + + /// Returns whether the given expression is an `else if`. + crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::If(..) = expr.kind { + let parent_id = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), + .. + })) = self.tcx.hir().find(parent_id) + { + return else_expr.hir_id == expr.hir_id; + } + } + false + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -652,6 +676,11 @@ }; let suggestion = if is_struct_pat_shorthand_field { format!("{}: *{}", code, code) + } else if self.is_else_if_block(expr) { + // Don't suggest nonsense like `else *if` + return None; + } else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) { + format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code)) } else { format!("*{}", code) }; @@ -1033,4 +1062,32 @@ _ => false, } } + + // Report the type inferred by the return statement. + fn report_closure_infered_return_type( + &self, + err: &mut DiagnosticBuilder<'_>, + expected: Ty<'tcx>, + ) { + if let Some(sp) = self.ret_coercion_span.get() { + // If the closure has an explicit return type annotation, + // then a type error may occur at the first return expression we + // see in the closure (if it conflicts with the declared + // return type). Skip adding a note in this case, since it + // would be incorrect. + if !err.span.primary_spans().iter().any(|&span| span == sp) { + let hir = self.tcx.hir(); + let body_owner = hir.body_owned_by(hir.enclosing_body_owner(self.body_id)); + if self.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { + err.span_note( + sp, + &format!( + "return type inferred to be `{}` here", + self.resolve_vars_if_possible(expected) + ), + ); + } + } + } + } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/dropck.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/dropck.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/dropck.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/dropck.rs 2021-06-17 03:53:51.000000000 +0000 @@ -354,9 +354,9 @@ fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/expectation.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/expectation.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/expectation.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/expectation.rs 2021-06-17 03:53:51.000000000 +0000 @@ -104,8 +104,8 @@ /// for the program to type-check). `only_has_type` will return /// such a constraint, if it exists. pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { - match self.resolve(fcx) { - ExpectHasType(ty) => Some(ty), + match self { + ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => { None } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/expr.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/expr.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/expr.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/expr.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,7 +6,7 @@ use crate::check::cast; use crate::check::coercion::CoerceMany; use crate::check::fatally_break_rust; -use crate::check::method::{probe, MethodError, SelfSource}; +use crate::check::method::SelfSource; use crate::check::report_unexpected_variant_res; use crate::check::BreakableCtxt; use crate::check::Diverges; @@ -30,7 +30,6 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -162,7 +161,7 @@ expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!(">> type-checking: expr={:?} expected={:?}", expr, expected); + debug!(">> type-checking: expected={:?}, expr={:?} ", expected, expr); // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block // without the final expr (e.g. `try { return; }`). We don't want to generate an @@ -225,7 +224,7 @@ expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!("check_expr_kind(expr={:?}, expected={:?})", expr, expected); + debug!("check_expr_kind(expected={:?}, expr={:?})", expected, expr); let tcx = self.tcx; match expr.kind { @@ -461,7 +460,11 @@ self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 } - fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> { + fn check_expr_path( + &self, + qpath: &'tcx hir::QPath<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span); let ty = match res { @@ -600,7 +603,7 @@ &cause, &mut |mut err| { self.suggest_mismatched_types_on_tail( - &mut err, expr, ty, e_ty, cause.span, target_id, + &mut err, expr, ty, e_ty, target_id, ); if let Some(val) = ty_kind_suggestion(ty) { let label = destination @@ -947,7 +950,16 @@ } Err(error) => { if segment.ident.name != kw::Empty { - self.report_extended_method_error(segment, span, args, rcvr_t, error); + if let Some(mut err) = self.report_method_error( + span, + rcvr_t, + segment.ident, + SelfSource::MethodCall(&args[0]), + error, + Some(args), + ) { + err.emit(); + } } Err(()) } @@ -964,59 +976,6 @@ ) } - fn report_extended_method_error( - &self, - segment: &hir::PathSegment<'_>, - span: Span, - args: &'tcx [hir::Expr<'tcx>], - rcvr_t: Ty<'tcx>, - error: MethodError<'tcx>, - ) { - let rcvr = &args[0]; - let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { - if let Some(new_rcvr_t) = new_rcvr_t { - if let Ok(pick) = self.lookup_probe( - span, - segment.ident, - new_rcvr_t, - rcvr, - probe::ProbeScope::AllTraits, - ) { - debug!("try_alt_rcvr: pick candidate {:?}", pick); - // Make sure the method is defined for the *actual* receiver: - // we don't want to treat `Box` as a receiver if - // it only works because of an autoderef to `&self` - if pick.autoderefs == 0 { - err.span_label( - pick.item.ident.span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); - } - } - } - }; - - if let Some(mut err) = self.report_method_error( - span, - rcvr_t, - segment.ident, - SelfSource::MethodCall(rcvr), - error, - Some(args), - ) { - if let ty::Adt(..) = rcvr_t.kind() { - // Try alternative arbitrary self types that could fulfill this call. - // FIXME: probe for all types that *could* be arbitrary self-types, not - // just this list. - try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox)); - try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin)); - try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc)); - try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc)); - } - err.emit(); - } - } - fn check_expr_cast( &self, e: &'tcx hir::Expr<'tcx>, @@ -2128,7 +2087,7 @@ fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { for (op, _op_sp) in asm.operands { match op { - hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr } => { + hir::InlineAsmOperand::In { expr, .. } => { self.check_expr_asm_operand(expr, true); } hir::InlineAsmOperand::Out { expr, .. } => { @@ -2145,6 +2104,9 @@ self.check_expr_asm_operand(out_expr, false); } } + hir::InlineAsmOperand::Const { anon_const } => { + self.to_const(anon_const); + } hir::InlineAsmOperand::Sym { expr } => { self.check_expr(expr); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs 2021-06-17 03:53:51.000000000 +0000 @@ -23,6 +23,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; use crate::structured_errors::StructuredDiagnostic; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -108,7 +109,7 @@ // 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 fn_inputs.iter().zip(args.iter()) { + for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs 2021-06-17 03:53:51.000000000 +0000 @@ -42,6 +42,7 @@ }; use std::collections::hash_map::Entry; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -904,12 +905,12 @@ /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. - pub fn resolve_ty_and_res_ufcs<'b>( + pub fn resolve_ty_and_res_ufcs( &self, - qpath: &'b QPath<'b>, + qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, - ) -> (Res, Option>, &'b [hir::PathSegment<'b>]) { + ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { @@ -1146,7 +1147,7 @@ ( hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }), - ) if last_bounds.iter().zip(exp_bounds.iter()).all(|(left, right)| { + ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| { match (left, right) { ( hir::GenericBound::Trait(tl, ml), @@ -1405,7 +1406,7 @@ (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.fcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.fcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), @@ -1443,10 +1444,14 @@ self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const => { - // FIXME(const_generics_defaults) - // No const parameters were provided, we have to infer them. - self.fcx.var_for_def(self.span, param) + GenericParamDefKind::Const { has_default, .. } => { + if !infer_args && has_default { + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() + } else { + self.fcx.var_for_def(self.span, param) + } } } } @@ -1459,7 +1464,7 @@ &[][..], has_self, self_ty, - arg_count, + &arg_count, &mut CreateCtorSubstsContext { fcx: self, span, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs 2021-06-17 03:53:51.000000000 +0000 @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, ItemKind, Node}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -41,21 +41,23 @@ expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, - cause_span: Span, blk_id: hir::HirId, ) -> bool { let expr = expr.peel_drop_temps(); // If the expression is from an external macro, then do not suggest // adding a semicolon, because there's nowhere to put it. // See issue #81943. - if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, cause_span) { - self.suggest_missing_semicolon(err, expr, expected, cause_span); + if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, expr.span) { + self.suggest_missing_semicolon(err, expr, expected); } let mut pointing_at_return_type = false; if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); - self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found); + let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + self.suggest_missing_break_or_return_expr( + err, expr, &fn_decl, expected, found, blk_id, fn_id, + ); } pointing_at_return_type } @@ -204,6 +206,7 @@ found: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) { + let expr = expr.peel_blocks(); if let Some((sp, msg, suggestion, applicability)) = self.check_ref(expr, found, expected) { err.span_suggestion(sp, msg, suggestion, applicability); } else if let (ty::FnDef(def_id, ..), true) = @@ -218,8 +221,7 @@ self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span); let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { - let mut suggestions = iter::repeat(&expr_text) - .zip(methods.iter()) + let mut suggestions = iter::zip(iter::repeat(&expr_text), &methods) .filter_map(|(receiver, method)| { let method_call = format!(".{}()", method.ident); if receiver.ends_with(&method_call) { @@ -388,7 +390,6 @@ err: &mut DiagnosticBuilder<'_>, expression: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, - cause_span: Span, ) { if expected.is_unit() { // `BlockTailExpression` only relevant if the tail expr would be @@ -403,7 +404,7 @@ if expression.can_have_side_effects() => { err.span_suggestion( - cause_span.shrink_to_hi(), + expression.span.shrink_to_hi(), "consider using a semicolon here", ";".to_string(), Applicability::MachineApplicable, @@ -473,21 +474,47 @@ } } - pub(in super::super) fn suggest_missing_return_expr( + pub(in super::super) fn suggest_missing_break_or_return_expr( &self, err: &mut DiagnosticBuilder<'_>, expr: &'tcx hir::Expr<'tcx>, fn_decl: &hir::FnDecl<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, + id: hir::HirId, + fn_id: hir::HirId, ) { if !expected.is_unit() { return; } let found = self.resolve_vars_with_obligations(found); + + let in_loop = self.is_loop(id) + || self.tcx.hir().parent_iter(id).any(|(parent_id, _)| self.is_loop(parent_id)); + + let in_local_statement = self.is_local_statement(id) + || self + .tcx + .hir() + .parent_iter(id) + .any(|(parent_id, _)| self.is_local_statement(parent_id)); + + if in_loop && in_local_statement { + err.multipart_suggestion( + "you might have meant to break the loop with this value", + vec![ + (expr.span.shrink_to_lo(), "break ".to_string()), + (expr.span.shrink_to_hi(), ";".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return; + } + if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(self, ty); - let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty)); + let bound_vars = self.tcx.late_bound_vars(fn_id); + let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); if self.can_coerce(found, ty) { err.multipart_suggestion( @@ -513,4 +540,14 @@ self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None); } } + + fn is_loop(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) + } + + fn is_local_statement(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/gather_locals.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/gather_locals.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/gather_locals.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/gather_locals.rs 2021-06-17 03:53:51.000000000 +0000 @@ -6,7 +6,6 @@ use rustc_middle::ty::Ty; use rustc_span::{sym, Span}; use rustc_trait_selection::traits; -use std::mem; pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -14,12 +13,12 @@ // parameters are special cases of patterns, but we want to handle them as // *distinct* cases. so track when we are hitting a pattern *within* an fn // parameter. - outermost_fn_param_pat: bool, + outermost_fn_param_pat: Option, } impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self { - Self { fcx, parent_id, outermost_fn_param_pat: false } + Self { fcx, parent_id, outermost_fn_param_pat: None } } fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option>) -> Ty<'tcx> { @@ -92,7 +91,7 @@ } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, true); + let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span); intravisit::walk_param(self, param); self.outermost_fn_param_pat = old_outermost_fn_param_pat; } @@ -102,12 +101,12 @@ if let PatKind::Binding(_, _, ident, _) = p.kind { let var_ty = self.assign(p.span, p.hir_id, None); - if self.outermost_fn_param_pat { + if let Some(ty_span) = self.outermost_fn_param_pat { if !self.fcx.tcx.features().unsized_fn_params { self.fcx.require_type_is_sized( var_ty, p.span, - traits::SizedArgumentType(Some(p.span)), + traits::SizedArgumentType(Some(ty_span)), ); } } else { @@ -123,7 +122,7 @@ var_ty ); } - let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, false); + let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take(); intravisit::walk_pat(self, p); self.outermost_fn_param_pat = old_outermost_fn_param_pat; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/generator_interior.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/generator_interior.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/generator_interior.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/generator_interior.rs 2021-06-17 03:53:51.000000000 +0000 @@ -186,7 +186,10 @@ // which means that none of the regions inside relate to any other, even if // typeck had previously found constraints that would cause them to be related. let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); counter += 1; r @@ -202,11 +205,15 @@ // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); + let bound_vars = fcx.tcx.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + let witness = + fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); // Store the generator types and spans into the typeck results for this generator. visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types = - ty::Binder::bind(type_causes); + ty::Binder::bind_with_vars(type_causes, bound_vars); debug!( "types in generator after region replacement {:?}, span = {:?}", diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/intrinsic.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/intrinsic.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/intrinsic.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/intrinsic.rs 2021-06-17 03:53:51.000000000 +0000 @@ -101,12 +101,21 @@ let intrinsic_name = tcx.item_name(it.def_id.to_def_id()); let name_str = intrinsic_name.as_str(); + let bound_vars = tcx.mk_bound_variable_kinds( + [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)] + .iter() + .copied(), + ); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = tcx - .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) })); - let env_region = - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv })); + let region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }, + )); + let env_region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, + )); let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) }) @@ -305,7 +314,7 @@ tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; - let br = ty::BoundRegion { kind: ty::BrAnon(0) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; ( 1, vec![ @@ -366,7 +375,7 @@ (n_tps, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); - let sig = ty::Binder::bind(sig); + let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, it, n_tps, sig) } @@ -398,8 +407,8 @@ | sym::simd_fpow | sym::simd_saturating_add | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), - sym::simd_neg => (1, vec![param(0)], param(0)), - sym::simd_fsqrt + sym::simd_neg + | sym::simd_fsqrt | sym::simd_fsin | sym::simd_fcos | sym::simd_fexp @@ -408,8 +417,10 @@ | sym::simd_flog10 | sym::simd_flog | sym::simd_fabs + | sym::simd_ceil | sym::simd_floor - | sym::simd_ceil => (1, vec![param(0)], param(0)), + | sym::simd_round + | sym::simd_trunc => (1, vec![param(0)], param(0)), sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/confirm.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/confirm.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/confirm.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/confirm.rs 2021-06-17 03:53:51.000000000 +0000 @@ -15,6 +15,7 @@ use rustc_span::Span; use rustc_trait_selection::traits; +use std::iter; use std::ops::Deref; struct ConfirmContext<'a, 'tcx> { @@ -118,7 +119,7 @@ // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if illegal_sized_bound.is_none() { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig)); + let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); self.add_obligations(method_ty, all_substs, method_predicates); } @@ -358,7 +359,7 @@ (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.cfcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), @@ -380,7 +381,7 @@ parent_substs, false, None, - arg_count_correct, + &arg_count_correct, &mut MethodSubstsCtxt { cfcx: self, pick, seg }, ) } @@ -496,10 +497,7 @@ // We don't care about regions here. .filter_map(|obligation| match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { - let span = predicates - .predicates - .iter() - .zip(predicates.spans.iter()) + let span = iter::zip(&predicates.predicates, &predicates.spans) .find_map( |(p, span)| { if *p == obligation.predicate { Some(*span) } else { None } @@ -552,7 +550,7 @@ upcast_trait_refs.into_iter().next().unwrap() } - fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder) -> T + fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -45,6 +45,7 @@ pub sig: ty::FnSig<'tcx>, } +#[derive(Debug)] pub enum MethodError<'tcx> { // Did not find an applicable method, but we did find various near-misses that may work. NoMatch(NoMatchData<'tcx>), @@ -66,6 +67,7 @@ // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which // could lead to matches if satisfied, and a list of not-in-scope traits which may work. +#[derive(Debug)] pub struct NoMatchData<'tcx> { pub static_candidates: Vec, pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, @@ -308,7 +310,7 @@ // Construct a trait-reference `self_ty : Trait` let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {} + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} GenericParamDefKind::Type { .. } => { if param.index == 0 { return self_ty.into(); @@ -397,7 +399,7 @@ obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/probe.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/probe.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/probe.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/probe.rs 2021-06-17 03:53:51.000000000 +0000 @@ -83,6 +83,8 @@ unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, is_suggestion: IsSuggestion, + + scope_expr_id: hir::HirId, } impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { @@ -156,7 +158,7 @@ /// When adjusting a receiver we often want to do one of /// -/// - Add a `&` (or `&mut`), converting the recevier from `T` to `&T` (or `&mut T`) +/// - Add a `&` (or `&mut`), converting the receiver from `T` to `&T` (or `&mut T`) /// - If the receiver has type `*mut T`, convert it to `*const T` /// /// This type tells us which one to do. @@ -448,6 +450,7 @@ orig_values, steps.steps, is_suggestion, + scope_expr_id, ); probe_cx.assemble_inherent_candidates(); @@ -547,6 +550,7 @@ orig_steps_var_values: OriginalQueryValues<'tcx>, steps: Lrc>>, is_suggestion: IsSuggestion, + scope_expr_id: hir::HirId, ) -> ProbeContext<'a, 'tcx> { ProbeContext { fcx, @@ -564,6 +568,7 @@ private_candidate: None, unsatisfied_predicates: Vec::new(), is_suggestion, + scope_expr_id, } } @@ -1312,7 +1317,7 @@ ) { self.tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, - self.fcx.body_id, + self.scope_expr_id, self.span, |lint| { let def_kind = stable_pick.item.kind.as_def_kind(); @@ -1456,6 +1461,16 @@ } TraitCandidate(trait_ref) => { + if let Some(method_name) = self.method_name { + // Some trait methods are excluded for arrays before 2021. + // (`array.into_iter()` wants a slice iterator for compatibility.) + if self_ty.is_array() && !method_name.span.rust_2021() { + let trait_def = self.tcx.trait_def(trait_ref.def_id); + if trait_def.skip_array_during_method_dispatch { + return ProbeResult::NoMatch; + } + } + } let predicate = trait_ref.without_const().to_predicate(self.tcx); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { @@ -1594,6 +1609,7 @@ self.orig_steps_var_values.clone(), steps, IsSuggestion(true), + self.scope_expr_id, ); pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); @@ -1700,7 +1716,7 @@ // In general, during probe we erase regions. self.tcx.lifetimes.re_erased.into() } - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { self.var_for_def(self.span, param) } } @@ -1753,7 +1769,7 @@ /// region got replaced with the same variable, which requires a bit more coordination /// and/or tracking the substitution and /// so forth. - fn erase_late_bound_regions(&self, value: ty::Binder) -> T + fn erase_late_bound_regions(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { @@ -1762,7 +1778,9 @@ /// Finds the method with the appropriate name (or return type, as the case may be). If /// `allow_similar_names` is set, find methods with close-matching names. - fn impl_or_trait_item(&self, def_id: DefId) -> Vec { + // The length of the returned iterator is nearly always 0 or 1 and this + // method is fairly hot. + fn impl_or_trait_item(&self, def_id: DefId) -> SmallVec<[ty::AssocItem; 1]> { if let Some(name) = self.method_name { if self.allow_similar_names { let max_dist = max(name.as_str().len(), 3) / 3; @@ -1778,7 +1796,7 @@ } else { self.fcx .associated_item(def_id, name, Namespace::ValueNS) - .map_or_else(Vec::new, |x| vec![x]) + .map_or_else(SmallVec::new, |x| SmallVec::from_buf([x])) } } else { self.tcx.associated_items(def_id).in_definition_order().copied().collect() diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/suggest.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/suggest.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/method/suggest.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/method/suggest.rs 2021-06-17 03:53:51.000000000 +0000 @@ -68,12 +68,12 @@ } } - pub fn report_method_error<'b>( + pub fn report_method_error( &self, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> Option> { @@ -323,8 +323,8 @@ err.span_suggestion( lit.span, &format!( - "you must specify a concrete type for \ - this numeric value, like `{}`", + "you must specify a concrete type for this numeric value, \ + like `{}`", concrete_type ), format!("{}_{}", snippet, concrete_type), @@ -579,6 +579,7 @@ } let mut restrict_type_params = false; + let mut unsatisfied_bounds = false; if !unsatisfied_predicates.is_empty() { let def_span = |def_id| { self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) @@ -739,6 +740,7 @@ err.note(&format!( "the following trait bounds were not satisfied:\n{bound_list}" )); + unsatisfied_bounds = true; } } @@ -752,6 +754,7 @@ source, out_of_scope_traits, &unsatisfied_predicates, + unsatisfied_bounds, ); } @@ -975,16 +978,100 @@ } } - fn suggest_traits_to_import<'b>( + fn suggest_traits_to_import( &self, err: &mut DiagnosticBuilder<'_>, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], + unsatisfied_bounds: bool, ) { + let mut alt_rcvr_sugg = false; + if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) { + debug!(?span, ?item_name, ?rcvr_ty, ?rcvr); + let skippable = [ + self.tcx.lang_items().clone_trait(), + self.tcx.lang_items().deref_trait(), + self.tcx.lang_items().deref_mut_trait(), + self.tcx.lang_items().drop_trait(), + ]; + // Try alternative arbitrary self types that could fulfill this call. + // FIXME: probe for all types that *could* be arbitrary self-types, not + // just this list. + for (rcvr_ty, post) in &[ + (rcvr_ty, ""), + (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "), + (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"), + ] { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + rcvr_ty, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + // If the method is defined for the receiver we have, it likely wasn't `use`d. + // We point at the method, but we just skip the rest of the check for arbitrary + // self types and rely on the suggestion to `use` the trait from + // `suggest_valid_traits`. + let did = Some(pick.item.container.id()); + let skip = skippable.contains(&did); + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", rcvr_ty), + ); + } + break; + } + for (rcvr_ty, pre) in &[ + (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"), + (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"), + ] { + if let Some(new_rcvr_t) = *rcvr_ty { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + debug!("try_alt_rcvr: pick candidate {:?}", pick); + let did = Some(pick.item.container.id()); + // We don't want to suggest a container type when the missing + // method is `.clone()` or `.deref()` otherwise we'd suggest + // `Arc::new(foo).clone()`, which is far from what the user wants. + let skip = skippable.contains(&did); + // Make sure the method is defined for the *actual* receiver: we don't + // want to treat `Box` as a receiver if it only works because of + // an autoderef to `&self` + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + err.multipart_suggestion( + "consider wrapping the receiver expression with the \ + appropriate type", + vec![ + (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), + (rcvr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; + } + } + } + } + } + } if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } @@ -1075,6 +1162,9 @@ "the method might not be found because of this arbitrary self type", ); } + if alt_rcvr_sugg { + return; + } if !candidates.is_empty() { // Sort from most relevant to least relevant. @@ -1284,7 +1374,12 @@ /// Checks whether there is a local type somewhere in the chain of /// autoderefs of `rcvr_ty`. - fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool { + fn type_derefs_to_local( + &self, + span: Span, + rcvr_ty: Ty<'tcx>, + source: SelfSource<'tcx>, + ) -> bool { fn is_local(ty: Ty<'_>) -> bool { match ty.kind() { ty::Adt(def, _) => def.did.is_local(), @@ -1310,7 +1405,7 @@ } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum SelfSource<'a> { QPath(&'a hir::Ty<'a>), MethodCall(&'a hir::Expr<'a> /* rcvr */), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/mod.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/mod.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/mod.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/mod.rs 2021-06-17 03:53:51.000000000 +0000 @@ -116,7 +116,6 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType}; use rustc_session::config; use rustc_session::parse::feature_err; @@ -497,6 +496,7 @@ let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn( &fcx, + id, header.unsafety, header.abi, decl, @@ -539,6 +539,25 @@ kind: TypeVariableOriginKind::TypeInference, span, }), + Node::Ty(&hir::Ty { + kind: hir::TyKind::Typeof(ref anon_const), .. + }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }), + Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(ia), .. }) + if ia.operands.iter().any(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } => { + anon_const.hir_id == id + } + _ => false, + }) => + { + fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }) + } _ => fallback(), }, _ => fallback(), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/pat.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/pat.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/pat.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/pat.rs 2021-06-17 03:53:51.000000000 +0000 @@ -861,7 +861,7 @@ fn check_pat_tuple_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &'tcx hir::QPath<'tcx>, subpats: &'tcx [&'tcx Pat<'tcx>], ddpos: Option, expected: Ty<'tcx>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/upvar.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/upvar.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/upvar.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/upvar.rs 2021-06-17 03:53:51.000000000 +0000 @@ -30,11 +30,11 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use super::writeback::Resolver; use super::FnCtxt; use crate::expr_use_visitor as euv; use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; @@ -42,7 +42,6 @@ use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults, UpvarSubsts}; use rustc_session::lint; use rustc_span::sym; @@ -51,6 +50,8 @@ use rustc_index::vec::Idx; use rustc_target::abi::VariantIdx; +use std::iter; + /// Describe the relationship between the paths of two places /// eg: /// - `foo` is ancestor of `foo.bar.baz` @@ -91,7 +92,7 @@ if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.kind { let body = self.fcx.tcx.hir().body(body_id); self.visit_body(body); - self.fcx.analyze_closure(expr.hir_id, expr.span, body, cc); + self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc); } intravisit::walk_expr(self, expr); @@ -104,6 +105,7 @@ &self, closure_hir_id: hir::HirId, span: Span, + body_id: hir::BodyId, body: &'tcx hir::Body<'tcx>, capture_clause: hir::CaptureBy, ) { @@ -167,7 +169,7 @@ let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); if should_do_migration_analysis(self.tcx, closure_hir_id) { - self.perform_2229_migration_anaysis(closure_def_id, capture_clause, span, body); + self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span); } // We now fake capture information for all variables that are mentioned within the closure @@ -465,20 +467,20 @@ fn perform_2229_migration_anaysis( &self, closure_def_id: DefId, + body_id: hir::BodyId, capture_clause: hir::CaptureBy, span: Span, - body: &'tcx hir::Body<'tcx>, ) { let need_migrations = self.compute_2229_migrations( closure_def_id, span, capture_clause, - body, self.typeck_results.borrow().closure_min_captures.get(&closure_def_id), ); if !need_migrations.is_empty() { - let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations); + let (migration_string, migrated_variables_concat) = + migration_suggestion_for_2229(self.tcx, &need_migrations); let local_def_id = closure_def_id.expect_local(); let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); @@ -490,7 +492,35 @@ let mut diagnostics_builder = lint.build( "drop order affected for closure because of `capture_disjoint_fields`", ); - diagnostics_builder.note(&migrations_text); + let closure_body_span = self.tcx.hir().span(body_id.hir_id); + let (sugg, app) = + match self.tcx.sess.source_map().span_to_snippet(closure_body_span) { + Ok(s) => { + let trimmed = s.trim_start(); + + // If the closure contains a block then replace the opening brace + // with "{ let _ = (..); " + let sugg = if let Some('{') = trimmed.chars().next() { + format!("{{ {}; {}", migration_string, &trimmed[1..]) + } else { + format!("{{ {}; {} }}", migration_string, s) + }; + (sugg, Applicability::MachineApplicable) + } + Err(_) => (migration_string.clone(), Applicability::HasPlaceholders), + }; + + let diagnostic_msg = format!( + "add a dummy let to cause {} to be fully captured", + migrated_variables_concat + ); + + diagnostics_builder.span_suggestion( + closure_body_span, + &diagnostic_msg, + sugg, + app, + ); diagnostics_builder.emit(); }, ); @@ -511,19 +541,8 @@ closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, - body: &'tcx hir::Body<'tcx>, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, ) -> Vec { - fn resolve_ty>( - fcx: &FnCtxt<'_, 'tcx>, - span: Span, - body: &'tcx hir::Body<'tcx>, - ty: T, - ) -> T { - let mut resolver = Resolver::new(fcx, &span, body); - ty.fold_with(&mut resolver) - } - let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { upvars } else { @@ -533,7 +552,7 @@ let mut need_migrations = Vec::new(); for (&var_hir_id, _) in upvars.iter() { - let ty = resolve_ty(self, closure_span, body, self.node_ty(var_hir_id)); + let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { continue; @@ -634,7 +653,7 @@ /// `w[c]`. /// Notation: /// - Ty(place): Type of place - /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_projs` + /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs` /// respectively. /// ``` /// (Ty(w), [ &[p, x], &[c] ]) @@ -695,7 +714,7 @@ closure_def_id: DefId, closure_span: Span, base_path_ty: Ty<'tcx>, - captured_projs: Vec<&[Projection<'tcx>]>, + captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { let needs_drop = |ty: Ty<'tcx>| { ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) @@ -720,9 +739,9 @@ // // eg. If `a.b` is captured and we are processing `a.b`, then we can't have the closure also // capture `a.b.c`, because that voilates min capture. - let is_completely_captured = captured_projs.iter().any(|projs| projs.is_empty()); + let is_completely_captured = captured_by_move_projs.iter().any(|projs| projs.is_empty()); - assert!(!is_completely_captured || (captured_projs.len() == 1)); + assert!(!is_completely_captured || (captured_by_move_projs.len() == 1)); if is_completely_captured { // The place is captured entirely, so doesn't matter if needs dtor, it will be drop @@ -730,23 +749,27 @@ return false; } + if captured_by_move_projs.is_empty() { + return needs_drop(base_path_ty); + } + if is_drop_defined_for_ty { // If drop is implemented for this type then we need it to be fully captured, - // which we know it is not because of the previous check. Therefore we need to - // do migrate. - return true; - } + // and we know it is not completely captured because of the previous checks. - if captured_projs.is_empty() { - return needs_drop(base_path_ty); + // Note that this is a bug in the user code that will be reported by the + // borrow checker, since we can't move out of drop types. + + // The bug exists in the user's code pre-migration, and we don't migrate here. + return false; } match base_path_ty.kind() { // Observations: - // - `captured_projs` is not empty. Therefore we can call - // `captured_projs.first().unwrap()` safely. - // - All entries in `captured_projs` have atleast one projection. - // Therefore we can call `captured_projs.first().unwrap().first().unwrap()` safely. + // - `captured_by_move_projs` is not empty. Therefore we can call + // `captured_by_move_projs.first().unwrap()` safely. + // - All entries in `captured_by_move_projs` have atleast one projection. + // Therefore we can call `captured_by_move_projs.first().unwrap().first().unwrap()` safely. // We don't capture derefs in case of move captures, which would have be applied to // access any further paths. @@ -756,19 +779,19 @@ ty::Adt(def, substs) => { // Multi-varaint enums are captured in entirety, - // which would've been handled in the case of single empty slice in `captured_projs`. + // which would've been handled in the case of single empty slice in `captured_by_move_projs`. assert_eq!(def.variants.len(), 1); // Only Field projections can be applied to a non-box Adt. assert!( - captured_projs.iter().all(|projs| matches!( + captured_by_move_projs.iter().all(|projs| matches!( projs.first().unwrap().kind, ProjectionKind::Field(..) )) ); def.variants.get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any( |(i, field)| { - let paths_using_field = captured_projs + let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { if let ProjectionKind::Field(field_idx, _) = @@ -795,14 +818,14 @@ ty::Tuple(..) => { // Only Field projections can be applied to a tuple. assert!( - captured_projs.iter().all(|projs| matches!( + captured_by_move_projs.iter().all(|projs| matches!( projs.first().unwrap().kind, ProjectionKind::Field(..) )) ); base_path_ty.tuple_fields().enumerate().any(|(i, element_ty)| { - let paths_using_field = captured_projs + let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { if let ProjectionKind::Field(field_idx, _) = projs.first().unwrap().kind @@ -1528,12 +1551,29 @@ !matches!(level, lint::Level::Allow) } -fn migration_suggestion_for_2229(tcx: TyCtxt<'_>, need_migrations: &Vec) -> String { - let need_migrations_strings = - need_migrations.iter().map(|v| format!("{}", var_name(tcx, *v))).collect::>(); - let migrations_list_concat = need_migrations_strings.join(", "); +/// Return a two string tuple (s1, s2) +/// - s1: Line of code that is needed for the migration: eg: `let _ = (&x, ...)`. +/// - s2: Comma separated names of the variables being migrated. +fn migration_suggestion_for_2229( + tcx: TyCtxt<'_>, + need_migrations: &Vec, +) -> (String, String) { + let need_migrations_variables = + need_migrations.iter().map(|v| var_name(tcx, *v)).collect::>(); + + let migration_ref_concat = + need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); + + let migration_string = if 1 == need_migrations.len() { + format!("let _ = {}", migration_ref_concat) + } else { + format!("let _ = ({})", migration_ref_concat) + }; + + let migrated_variables_concat = + need_migrations_variables.iter().map(|v| format!("`{}`", v)).collect::>().join(", "); - format!("drop(&({}));", migrations_list_concat) + (migration_string, migrated_variables_concat) } /// Helper function to determine if we need to escalate CaptureKind from @@ -1548,7 +1588,7 @@ /// If both the CaptureKind and Expression are considered to be equivalent, /// then `CaptureInfo` A is preferred. This can be useful in cases where we want to priortize /// expressions reported back to the user as part of diagnostics based on which appears earlier -/// in the closure. This can be acheived simply by calling +/// in the closure. This can be achieved simply by calling /// `determine_capture_info(existing_info, current_info)`. This works out because the /// expressions that occur earlier in the closure body than the current expression are processed before. /// Consider the following example @@ -1646,7 +1686,7 @@ let projections_b = &place_b.projections; let same_initial_projections = - projections_a.iter().zip(projections_b.iter()).all(|(proj_a, proj_b)| proj_a == proj_b); + iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b); if same_initial_projections { // First min(n, m) projections are the same diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/wfcheck.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/wfcheck.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/wfcheck.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/wfcheck.rs 2021-06-17 03:53:51.000000000 +0000 @@ -24,6 +24,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use std::iter; use std::ops::ControlFlow; /// Helper type of a temporary returned by `.for_item(...)`. @@ -314,17 +315,20 @@ ), ) } else { - tcx.sess - .struct_span_err( - hir_ty.span, - &format!( - "{} is forbidden as the type of a const generic parameter", - unsupported_type - ), - ) - .note("the only supported types are integers, `bool` and `char`") - .help("more complex types are supported with `#![feature(const_generics)]`") - .emit() + let mut err = tcx.sess.struct_span_err( + hir_ty.span, + &format!( + "{} is forbidden as the type of a const generic parameter", + unsupported_type + ), + ); + err.note("the only supported types are integers, `bool` and `char`"); + if tcx.sess.is_nightly_build() { + err.help( + "more complex types are supported with `#![feature(const_generics)]`", + ); + } + err.emit() } }; @@ -713,10 +717,11 @@ let generics = tcx.generics_of(def_id); let is_our_default = |def: &ty::GenericParamDef| match def.kind { - GenericParamDefKind::Type { has_default, .. } => { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => { has_default && def.index >= generics.parent_count as u32 } - _ => unreachable!(), + GenericParamDefKind::Lifetime => unreachable!(), }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. @@ -726,20 +731,36 @@ // // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { - if let GenericParamDefKind::Type { .. } = param.kind { - if is_our_default(¶m) { - let ty = fcx.tcx.type_of(param.def_id); - // Ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ``). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + match param.kind { + GenericParamDefKind::Type { .. } => { + if is_our_default(¶m) { + let ty = fcx.tcx.type_of(param.def_id); + // Ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ``). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation( + ty.into(), + fcx.tcx.def_span(param.def_id), + ObligationCauseCode::MiscObligation, + ); + } + } + } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): Figure out if this + // is the behavior we want, see the comment further below. + if is_our_default(¶m) { + let default_ct = tcx.const_param_default(param.def_id); fcx.register_wf_obligation( - ty.into(), + default_ct.into(), fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation, ); } } + // Doesn't have defaults. + GenericParamDefKind::Lifetime => {} } } @@ -771,9 +792,25 @@ fcx.tcx.mk_param_from_def(param) } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): I(@lcnr) feel like always + // using the const parameter is the right choice here, even + // if it needs substs. + // + // Before stabilizing this we probably want to get some tests + // where this makes a difference and figure out what's the exact + // behavior we want here. + + // If the param has a default, ... + if is_our_default(param) { + let default_ct = tcx.const_param_default(param.def_id); + // ... and it's not a dependent default, ... + if !default_ct.needs_subst() { + // ... then substitute it with the default. + return default_ct.into(); + } + } - GenericParamDefKind::Const => { - // FIXME(const_generics_defaults) fcx.tcx.mk_param_from_def(param) } } @@ -857,7 +894,7 @@ debug!("check_where_clauses: predicates={:?}", predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = - predicates.predicates.iter().zip(predicates.spans.iter()).flat_map(|(&p, &sp)| { + iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, sp) }); @@ -879,8 +916,8 @@ let sig = fcx.normalize_associated_types_in(span, sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) { - fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation); + for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) { + fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); @@ -1060,13 +1097,14 @@ debug!("check_method_receiver: sig={:?}", sig); let self_ty = fcx.normalize_associated_types_in(span, self_ty); - let self_ty = fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty)); + let self_ty = + fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx)); let receiver_ty = sig.inputs()[0]; let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty); let receiver_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty)); + fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx)); if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/writeback.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/writeback.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/check/writeback.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/check/writeback.rs 2021-06-17 03:53:51.000000000 +0000 @@ -675,7 +675,7 @@ /// The Resolver. This is the type folding engine that detects /// unresolved types and so forth. -crate struct Resolver<'cx, 'tcx> { +struct Resolver<'cx, 'tcx> { tcx: TyCtxt<'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>, span: &'cx dyn Locatable, @@ -686,7 +686,7 @@ } impl<'cx, 'tcx> Resolver<'cx, 'tcx> { - crate fn new( + fn new( fcx: &'cx FnCtxt<'cx, 'tcx>, span: &'cx dyn Locatable, body: &'tcx hir::Body<'tcx>, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs 2021-06-17 03:53:51.000000000 +0000 @@ -24,8 +24,8 @@ /// namespace. fn impls_have_common_items( &self, - impl_items1: &ty::AssociatedItems<'_>, - impl_items2: &ty::AssociatedItems<'_>, + impl_items1: &ty::AssocItems<'_>, + impl_items2: &ty::AssocItems<'_>, ) -> bool { let mut impl_items1 = &impl_items1; let mut impl_items2 = &impl_items2; diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/collect/type_of.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/collect/type_of.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/collect/type_of.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/collect/type_of.rs 2021-06-17 03:53:51.000000000 +0000 @@ -83,7 +83,7 @@ return generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id); } @@ -121,7 +121,7 @@ tcx.generics_of(type_dependent_def) .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(idx) .map(|param| param.def_id) } @@ -191,7 +191,25 @@ Res::Def(DefKind::Ctor(..), def_id) => { tcx.generics_of(tcx.parent(def_id).unwrap()) } - Res::Def(_, def_id) => tcx.generics_of(def_id), + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => tcx.generics_of(def_id), Res::Err => { tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); return None; @@ -211,7 +229,7 @@ generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id) } @@ -417,12 +435,14 @@ let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) - | Node::Ty(&Ty { kind: TyKind::Typeof(ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) if constant.hir_id == hir_id => { tcx.types.usize } + Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { + tcx.typeck(def_id).node_type(e.hir_id) + } Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. }) if anon_const.hir_id == hir_id => @@ -430,12 +450,27 @@ tcx.typeck(def_id).node_type(anon_const.hir_id) } + Node::Expr(&Expr { kind: ExprKind::InlineAsm(ia), .. }) + if ia.operands.iter().any(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id, + _ => false, + }) => + { + tcx.typeck(def_id).node_type(hir_id) + } + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx .adt_def(tcx.hir().get_parent_did(hir_id).to_def_id()) .repr .discr_type() .to_ty(tcx), + Node::GenericParam(&GenericParam { + hir_id: param_hir_id, + kind: GenericParamKind::Const { default: Some(ct), .. }, + .. + }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), + x => tcx.ty_error_with_message( DUMMY_SP, &format!("unexpected const parent in type_of_def_id(): {:?}", x), diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/collect.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/collect.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/collect.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/collect.rs 2021-06-17 03:53:51.000000000 +0000 @@ -43,13 +43,13 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; -use rustc_session::config::SanitizerSet; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::spec::abi; +use rustc_target::spec::{abi, SanitizerSet}; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use std::iter; mod item_bounds; mod type_of; @@ -254,10 +254,15 @@ self.tcx.ensure().type_of(def_id); } hir::GenericParamKind::Type { .. } => {} - hir::GenericParamKind::Const { .. } => { + hir::GenericParamKind::Const { default, .. } => { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); - // FIXME(const_generics_defaults) + if let Some(default) = default { + let default_def_id = self.tcx.hir().local_def_id(default.hir_id); + // need to store default and type of default + self.tcx.ensure().type_of(default_def_id); + self.tcx.ensure().const_param_default(def_id); + } } } } @@ -729,8 +734,14 @@ tcx.ensure().generics_of(item.def_id); tcx.ensure().type_of(item.def_id); tcx.ensure().predicates_of(item.def_id); - if let hir::ForeignItemKind::Fn(..) = item.kind { - tcx.ensure().fn_sig(item.def_id); + match item.kind { + hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), + hir::ForeignItemKind::Static(..) => { + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_foreign_item(item); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); + } + _ => (), } } } @@ -1178,6 +1189,8 @@ } let is_marker = tcx.has_attr(def_id, sym::marker); + let skip_array_during_method_dispatch = + tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch); let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { ty::trait_def::TraitSpecializationKind::Marker } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) { @@ -1186,7 +1199,16 @@ ty::trait_def::TraitSpecializationKind::None }; let def_path_hash = tcx.def_path_hash(def_id); - ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, spec_kind, def_path_hash) + ty::TraitDef::new( + def_id, + unsafety, + paren_sugar, + is_auto, + is_marker, + skip_array_during_method_dispatch, + spec_kind, + def_path_hash, + ) } fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option { @@ -1238,7 +1260,8 @@ match self.tcx.named_region(lt.hir_id) { Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {} Some( - rl::Region::LateBound(debruijn, _, _) | rl::Region::LateBoundAnon(debruijn, _), + rl::Region::LateBound(debruijn, _, _, _) + | rl::Region::LateBoundAnon(debruijn, _, _), ) if debruijn < self.outer_index => {} Some( rl::Region::LateBound(..) @@ -1302,13 +1325,13 @@ } } -struct AnonConstInParamListDetector { - in_param_list: bool, - found_anon_const_in_list: bool, +struct AnonConstInParamTyDetector { + in_param_ty: bool, + found_anon_const_in_param_ty: bool, ct: HirId, } -impl<'v> Visitor<'v> for AnonConstInParamListDetector { +impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1316,15 +1339,17 @@ } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - let prev = self.in_param_list; - self.in_param_list = true; - intravisit::walk_generic_param(self, p); - self.in_param_list = prev; + if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + let prev = self.in_param_ty; + self.in_param_ty = true; + self.visit_ty(ty); + self.in_param_ty = prev; + } } fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { - if self.in_param_list && self.ct == c.hir_id { - self.found_anon_const_in_list = true; + if self.in_param_ty && self.ct == c.hir_id { + self.found_anon_const_in_param_ty = true; } else { intravisit::walk_anon_const(self, c) } @@ -1352,27 +1377,24 @@ let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let mut in_param_list = false; + let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamListDetector { - in_param_list: false, - found_anon_const_in_list: false, + let mut visitor = AnonConstInParamTyDetector { + in_param_ty: false, + found_anon_const_in_param_ty: false, ct: hir_id, }; visitor.visit_generics(generics); - in_param_list = visitor.found_anon_const_in_list; + in_param_ty = visitor.found_anon_const_in_param_ty; break; } } - if in_param_list { + if in_param_ty { // We do not allow generic parameters in anon consts if we are inside - // of a param list. - // - // This affects both default type bindings, e.g. `struct()]>(T, U)`, - // and the types of const parameters, e.g. `struct V();`. + // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { // HACK(eddyb) this provides the correct generics when @@ -1523,7 +1545,7 @@ |lint| { lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", + `struct`, `enum`, `type`, or `trait` definitions", ) .emit(); }, @@ -1549,13 +1571,21 @@ i += 1; Some(param_def) } - GenericParamKind::Const { .. } => { + GenericParamKind::Const { default, .. } => { + if !allow_defaults && default.is_some() { + tcx.sess.span_err( + param.span, + "defaults for const parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions", + ); + } + let param_def = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Const, + kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, }; i += 1; Some(param_def) @@ -1693,10 +1723,11 @@ } diag.emit(); - ty::Binder::bind(fn_sig) + ty::Binder::bind(fn_sig, tcx) } None => >::ty_of_fn( &icx, + hir_id, sig.header.unsafety, sig.header.abi, &sig.decl, @@ -1714,6 +1745,7 @@ .. }) => >::ty_of_fn( &icx, + hir_id, header.unsafety, header.abi, decl, @@ -1735,13 +1767,10 @@ let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id()); let inputs = data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); - ty::Binder::bind(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust, - )) + ty::Binder::bind( + tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), + tcx, + ) } Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { @@ -2025,7 +2054,7 @@ param.bounds.iter().for_each(|bound| match bound { hir::GenericBound::Outlives(lt) => { let bound = >::ast_region_to_region(&icx, <, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound)); + let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx); predicates.insert((outlives.to_predicate(tcx), lt.span)); } _ => bug!(), @@ -2070,6 +2099,7 @@ match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(&bound_pred.bounded_ty); + let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` @@ -2085,9 +2115,13 @@ } else { let span = bound_pred.bounded_ty.span; let re_root_empty = tcx.lifetimes.re_root_empty; - let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, re_root_empty), - )); + let predicate = ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, + re_root_empty, + )), + bound_vars, + ); predicates.insert((predicate.to_predicate(tcx), span)); } } @@ -2104,10 +2138,12 @@ let mut bounds = Bounds::default(); let _ = >::instantiate_poly_trait_ref( &icx, - &poly_trait_ref, + &poly_trait_ref.trait_ref, + poly_trait_ref.span, constness, ty, &mut bounds, + false, ); predicates.extend(bounds.predicates(tcx, ty)); } @@ -2130,9 +2166,12 @@ let region = >::ast_region_to_region(&icx, lifetime, None); predicates.insert(( - ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, region), - )) + ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, region, + )), + bound_vars, + ) .to_predicate(tcx), lifetime.span, )); @@ -2212,10 +2251,11 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { let def_id = self.tcx.hir().local_def_id(c.hir_id); let ct = ty::Const::from_anon_const(self.tcx, def_id); - if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { + if let ty::ConstKind::Unevaluated(uv) = ct.val { + assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx), + ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx), span, )); } @@ -2353,7 +2393,14 @@ }; let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds); + let _ = astconv.instantiate_poly_trait_ref( + &tr.trait_ref, + tr.span, + constness, + param_ty, + &mut bounds, + false, + ); bounds.predicates(astconv.tcx(), param_ty) } hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { @@ -2389,8 +2436,10 @@ } else { hir::Unsafety::Unsafe }; + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let fty = >::ty_of_fn( &ItemCtxt::new(tcx, def_id), + hir_id, unsafety, abi, decl, @@ -2425,7 +2474,7 @@ .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) { + for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { check(&input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { @@ -2673,6 +2722,8 @@ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; } else if tcx.sess.check_name(attr, sym::no_mangle) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; + } else if tcx.sess.check_name(attr, sym::no_coverage) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; } else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } else if tcx.sess.check_name(attr, sym::used) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/expr_use_visitor.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/expr_use_visitor.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/expr_use_visitor.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/expr_use_visitor.rs 2021-06-17 03:53:51.000000000 +0000 @@ -18,6 +18,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, adjustment, TyCtxt}; use rustc_target::abi::VariantIdx; +use std::iter; use crate::mem_categorization as mc; @@ -279,9 +280,14 @@ if needs_to_be_read { self.borrow_expr(&discr, ty::ImmBorrow); } else { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForMatchedPlace, + FakeReadCause::ForMatchedPlace(closure_def_id), discr_place.hir_id, ); @@ -312,7 +318,6 @@ for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } - | hir::InlineAsmOperand::Const { expr, .. } | hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr), hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -328,12 +333,13 @@ self.mutate_expr(out_expr); } } + hir::InlineAsmOperand::Const { .. } => {} } } } hir::ExprKind::LlvmInlineAsm(ref ia) => { - for (o, output) in ia.inner.outputs.iter().zip(ia.outputs_exprs) { + for (o, output) in iter::zip(&ia.inner.outputs, ia.outputs_exprs) { if o.is_indirect { self.consume_expr(output); } else { @@ -577,9 +583,14 @@ } fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForMatchedPlace, + FakeReadCause::ForMatchedPlace(closure_def_id), discr_place.hir_id, ); self.walk_pat(discr_place, &arm.pat); @@ -594,9 +605,14 @@ /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForLet, + FakeReadCause::ForLet(closure_def_id), discr_place.hir_id, ); self.walk_pat(discr_place, pat); @@ -655,7 +671,7 @@ /// In the following example the closures `c` only captures `p.x`` even though `incr` /// is a capture of the nested closure /// - /// ```rust,ignore(cannot-test-this-because-pseduo-code) + /// ```rust,ignore(cannot-test-this-because-pseudo-code) /// let p = ..; /// let c = || { /// let incr = 10; @@ -699,7 +715,7 @@ // The only places we want to fake read before creating the parent closure are the ones that // are not local to it/ defined by it. // - // ```rust,ignore(cannot-test-this-because-pseduo-code) + // ```rust,ignore(cannot-test-this-because-pseudo-code) // let v1 = (0, 1); // let c = || { // fake reads: v1 // let v2 = (0, 1); diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/impl_wf_check.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/impl_wf_check.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/impl_wf_check.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/impl_wf_check.rs 2021-06-17 03:53:51.000000000 +0000 @@ -173,7 +173,7 @@ ); } } - ty::GenericParamDefKind::Const => { + ty::GenericParamDefKind::Const { .. } => { let param_ct = ty::ParamConst::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ct)) { report_unused_parameter( diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -63,8 +63,9 @@ #![feature(format_args_capture)] #![feature(in_band_lifetimes)] #![feature(is_sorted)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(try_blocks)] #![feature(never_type)] #![feature(slice_partition_dedup)] @@ -96,8 +97,8 @@ use rustc_errors::{struct_span_err, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; -use rustc_hir::Node; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::{Node, CRATE_HIR_ID}; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::middle; @@ -109,7 +110,7 @@ use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ - ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, + self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, }; use std::iter; @@ -163,106 +164,203 @@ }) } -fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) { - let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id); +fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { + let main_fnsig = tcx.fn_sig(main_def_id); let main_span = tcx.def_span(main_def_id); - let main_t = tcx.type_of(main_def_id); - match main_t.kind() { - ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir().find(main_id) { - if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { - let mut error = false; - if !generics.params.is_empty() { - let msg = "`main` function is not allowed to have generic \ - parameters" - .to_owned(); - let label = "`main` cannot have generic parameters".to_string(); - struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) - .span_label(generics.span, label) - .emit(); - error = true; - } - if let Some(sp) = generics.where_clause.span() { - struct_span_err!( - tcx.sess, - sp, - E0646, - "`main` function is not allowed to have a `where` clause" - ) - .span_label(sp, "`main` cannot have a `where` clause") - .emit(); - error = true; - } - if let hir::IsAsync::Async = sig.header.asyncness { - let span = tcx.sess.source_map().guess_head_span(it.span); - struct_span_err!( - tcx.sess, - span, - E0752, - "`main` function is not allowed to be `async`" - ) - .span_label(span, "`main` function is not allowed to be `async`") - .emit(); - error = true; - } - let attrs = tcx.hir().attrs(main_id); - for attr in attrs { - if tcx.sess.check_name(attr, sym::track_caller) { - tcx.sess - .struct_span_err( - attr.span, - "`main` function is not allowed to be `#[track_caller]`", - ) - .span_label( - main_span, - "`main` function is not allowed to be `#[track_caller]`", - ) - .emit(); - error = true; - } - } + fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId { + if let Some(local_def_id) = def_id.as_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); + let hir_type = tcx.type_of(local_def_id); + if !matches!(hir_type.kind(), ty::FnDef(..)) { + span_bug!(sp, "main has a non-function type: found `{}`", hir_type); + } + hir_id + } else { + CRATE_HIR_ID + } + } - if error { - return; - } - } + fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { + let generics_param_span = + if !generics.params.is_empty() { Some(generics.span) } else { None }; + generics_param_span + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); } + } + } - let actual = tcx.fn_sig(main_def_id); - let expected_return_type = if tcx.lang_items().termination().is_some() { - // we take the return type of the given main function, the real check is done - // in `check_fn` - actual.output() - } else { - // standard () main return type - ty::Binder::dummy(tcx.mk_unit()) - }; - - let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { - tcx.mk_fn_sig( - iter::empty(), - expected_return_type, - false, - hir::Unsafety::Normal, - Abi::Rust, - ) - })); + fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { + generics.where_clause.span() + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } + } + } - require_same_types( - tcx, - &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), - se_ty, - tcx.mk_fn_ptr(actual), - ); + fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; } - _ => { - span_bug!(main_span, "main has a non-function type: found `{}`", main_t); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { span: item_span, .. })) => { + Some(tcx.sess.source_map().guess_head_span(*item_span)) + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } + } + } + + fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => { + Some(fn_sig.decl.output.span()) + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } } } -} -fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) { + let mut error = false; + let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span); + let main_fn_generics = tcx.generics_of(main_def_id); + let main_fn_predicates = tcx.predicates_of(main_def_id); + if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { + let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); + let msg = "`main` function is not allowed to have generic \ + parameters"; + let mut diag = + struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg); + if let Some(generics_param_span) = generics_param_span { + let label = "`main` cannot have generic parameters".to_string(); + diag.span_label(generics_param_span, label); + } + diag.emit(); + error = true; + } else if !main_fn_predicates.predicates.is_empty() { + // generics may bring in implicit predicates, so we skip this check if generics is present. + let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); + let mut diag = struct_span_err!( + tcx.sess, + generics_where_clauses_span.unwrap_or(main_span), + E0646, + "`main` function is not allowed to have a `where` clause" + ); + if let Some(generics_where_clauses_span) = generics_where_clauses_span { + diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause"); + } + diag.emit(); + error = true; + } + + let main_asyncness = tcx.asyncness(main_def_id); + if let hir::IsAsync::Async = main_asyncness { + let mut diag = struct_span_err!( + tcx.sess, + main_span, + E0752, + "`main` function is not allowed to be `async`" + ); + let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); + if let Some(asyncness_span) = asyncness_span { + diag.span_label(asyncness_span, "`main` function is not allowed to be `async`"); + } + diag.emit(); + error = true; + } + + for attr in tcx.get_attrs(main_def_id) { + if tcx.sess.check_name(attr, sym::track_caller) { + tcx.sess + .struct_span_err( + attr.span, + "`main` function is not allowed to be `#[track_caller]`", + ) + .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`") + .emit(); + error = true; + } + } + + if error { + return; + } + + let expected_return_type; + if let Some(term_id) = tcx.lang_items().termination() { + let return_ty = main_fnsig.output(); + let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); + if !return_ty.bound_vars().is_empty() { + let msg = "`main` function return type is not allowed to have generic \ + parameters" + .to_owned(); + struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit(); + error = true; + } + let return_ty = return_ty.skip_binder(); + tcx.infer_ctxt().enter(|infcx| { + let cause = traits::ObligationCause::new( + return_ty_span, + main_diagnostics_hir_id, + ObligationCauseCode::MainFunctionType, + ); + let mut fulfillment_cx = traits::FulfillmentContext::new(); + fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause); + if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&err, None, false); + error = true; + } + }); + // now we can take the return type of the given main function + expected_return_type = main_fnsig.output(); + } else { + // standard () main return type + expected_return_type = ty::Binder::dummy(tcx.mk_unit()); + } + + if error { + return; + } + + let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { + tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) + })); + + require_same_types( + tcx, + &ObligationCause::new( + main_span, + main_diagnostics_hir_id, + ObligationCauseCode::MainFunctionType, + ), + se_ty, + tcx.mk_fn_ptr(main_fnsig), + ); +} +fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { + let start_def_id = start_def_id.expect_local(); let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id); @@ -429,7 +527,7 @@ let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id); let env_def_id = tcx.hir().local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); - item_cx.to_ty(hir_ty) + >::ast_ty_to_ty(&item_cx, hir_ty) } pub fn hir_trait_to_predicates<'tcx>( @@ -444,7 +542,7 @@ let env_def_id = tcx.hir().local_def_id(env_hir_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let mut bounds = Bounds::default(); - let _ = >::instantiate_poly_trait_ref_inner( + let _ = >::instantiate_poly_trait_ref( &item_cx, hir_trait, DUMMY_SP, diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/variance/solve.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/variance/solve.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_typeck/src/variance/solve.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_typeck/src/variance/solve.rs 2021-06-17 03:53:51.000000000 +0000 @@ -78,7 +78,7 @@ // Make all const parameters invariant. for param in generics.params.iter() { - if let ty::GenericParamDefKind::Const = param.kind { + if let ty::GenericParamDefKind::Const { .. } = param.kind { variances[param.index as usize] = ty::Invariant; } } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_type_ir/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_type_ir/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_type_ir/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_type_ir/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -1,7 +1,3 @@ -#![feature(never_type)] -#![feature(const_panic)] -#![feature(control_flow_enum)] - #[macro_use] extern crate bitflags; #[macro_use] diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/common_traits.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/common_traits.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/common_traits.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/common_traits.rs 2021-06-17 03:53:51.000000000 +0000 @@ -18,6 +18,10 @@ is_item_raw(tcx, query, LangItem::Freeze) } +fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + is_item_raw(tcx, query, LangItem::Unpin) +} + fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -37,5 +41,11 @@ } pub(crate) fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { is_copy_raw, is_sized_raw, is_freeze_raw, ..*providers }; + *providers = ty::query::Providers { + is_copy_raw, + is_sized_raw, + is_freeze_raw, + is_unpin_raw, + ..*providers + }; } diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/instance.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/instance.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/instance.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/instance.rs 2021-06-17 03:53:51.000000000 +0000 @@ -115,7 +115,7 @@ ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?; + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/lib.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/lib.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/lib.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/lib.rs 2021-06-17 03:53:51.000000000 +0000 @@ -20,6 +20,7 @@ mod common_traits; pub mod instance; mod needs_drop; +pub mod representability; mod ty; pub fn provide(providers: &mut Providers) { diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/representability.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/representability.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/representability.rs 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/representability.rs 2021-06-17 03:53:51.000000000 +0000 @@ -0,0 +1,186 @@ +//! Check whether a type is representable. +use rustc_data_structures::stable_map::FxHashMap; +use rustc_hir as hir; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; +use std::cmp; + +/// Describes whether a type is representable. For types that are not +/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to +/// distinguish between types that are recursive with themselves and types that +/// contain a different recursive type. These cases can therefore be treated +/// differently when reporting errors. +/// +/// The ordering of the cases is significant. They are sorted so that cmp::max +/// will keep the "more erroneous" of two values. +#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] +pub enum Representability { + Representable, + ContainsRecursive, + SelfRecursive(Vec), +} + +/// Check whether a type is representable. This means it cannot contain unboxed +/// structural recursion. This check is needed for structs and enums. +pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> Representability { + debug!("is_type_representable: {:?}", ty); + // To avoid a stack overflow when checking an enum variant or struct that + // contains a different, structurally recursive type, maintain a stack + // of seen types and check recursion for each of them (issues #3008, #3779). + let mut seen: Vec> = Vec::new(); + let mut representable_cache = FxHashMap::default(); + let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, ty); + debug!("is_type_representable: {:?} is {:?}", ty, r); + r +} + +// Iterate until something non-representable is found +fn fold_repr>(iter: It) -> Representability { + iter.fold(Representability::Representable, |r1, r2| match (r1, r2) { + (Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => { + Representability::SelfRecursive(v1.into_iter().chain(v2).collect()) + } + (r1, r2) => cmp::max(r1, r2), + }) +} + +fn are_inner_types_recursive<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + match ty.kind() { + ty::Tuple(..) => { + // Find non representable + fold_repr( + ty.tuple_fields().map(|ty| { + is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) + }), + ) + } + // Fixed-length vectors. + // FIXME(#11924) Behavior undecided for zero-length vectors. + ty::Array(ty, _) => is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty), + ty::Adt(def, substs) => { + // Find non representable fields with their spans + fold_repr(def.all_fields().map(|field| { + let ty = field.ty(tcx, substs); + let span = match field + .did + .as_local() + .map(|id| tcx.hir().local_def_id_to_hir_id(id)) + .and_then(|id| tcx.hir().find(id)) + { + Some(hir::Node::Field(field)) => field.ty.span, + _ => sp, + }; + match is_type_structurally_recursive(tcx, span, seen, representable_cache, ty) { + Representability::SelfRecursive(_) => { + Representability::SelfRecursive(vec![span]) + } + x => x, + } + })) + } + ty::Closure(..) => { + // this check is run on type definitions, so we don't expect + // to see closure types + bug!("requires check invoked on inapplicable type: {:?}", ty) + } + _ => Representability::Representable, + } +} + +fn same_adt<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { + match *ty.kind() { + ty::Adt(ty_def, _) => ty_def == def, + _ => false, + } +} + +// Does the type `ty` directly (without indirection through a pointer) +// contain any types on stack `seen`? +fn is_type_structurally_recursive<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); + if let Some(representability) = representable_cache.get(ty) { + debug!( + "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", + ty, sp, representability + ); + return representability.clone(); + } + + let representability = + is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty); + + representable_cache.insert(ty, representability.clone()); + representability +} + +fn is_type_structurally_recursive_inner<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + match ty.kind() { + ty::Adt(def, _) => { + { + // Iterate through stack of previously seen types. + let mut iter = seen.iter(); + + // The first item in `seen` is the type we are actually curious about. + // We want to return SelfRecursive if this type contains itself. + // It is important that we DON'T take generic parameters into account + // for this check, so that Bar in this example counts as SelfRecursive: + // + // struct Foo; + // struct Bar { x: Bar } + + if let Some(&seen_adt) = iter.next() { + if same_adt(seen_adt, *def) { + debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty); + return Representability::SelfRecursive(vec![sp]); + } + } + + // We also need to know whether the first item contains other types + // that are structurally recursive. If we don't catch this case, we + // will recurse infinitely for some inputs. + // + // It is important that we DO take generic parameters into account + // here, so that code like this is considered SelfRecursive, not + // ContainsRecursive: + // + // struct Foo { Option> } + + for &seen_adt in iter { + if ty::TyS::same_type(ty, seen_adt) { + debug!("ContainsRecursive: {:?} contains {:?}", seen_adt, ty); + return Representability::ContainsRecursive; + } + } + } + + // For structs and enums, track all previously seen types by pushing them + // onto the 'seen' stack. + seen.push(ty); + let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty); + seen.pop(); + out + } + _ => { + // No need to push in other cases. + are_inner_types_recursive(tcx, sp, seen, representable_cache, ty) + } + } +} diff -Nru rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/ty.rs rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/ty.rs --- rustc-1.52.1+dfsg1+llvm/compiler/rustc_ty_utils/src/ty.rs 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/compiler/rustc_ty_utils/src/ty.rs 2021-06-17 03:53:51.000000000 +0000 @@ -210,9 +210,9 @@ } } -fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> { +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssociatedItems::new(items) + ty::AssocItems::new(items) } fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { diff -Nru rustc-1.52.1+dfsg1+llvm/config.toml.example rustc-1.53.0+dfsg1+llvm/config.toml.example --- rustc-1.52.1+dfsg1+llvm/config.toml.example 2021-05-09 02:52:39.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/config.toml.example 2021-06-17 03:53:51.000000000 +0000 @@ -112,6 +112,7 @@ # When invoking `llvm-config` this configures whether the `--shared` argument is # passed to prefer linking to shared libraries. +# NOTE: `thin-lto = true` requires this to be `true` and will give an error otherwise. #link-shared = false # When building llvm, this configures what is being appended to the version. @@ -120,22 +121,23 @@ #version-suffix = "-rust-dev" # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass -# with clang-cl, so this is special in that it only compiles LLVM with clang-cl -#clang-cl = '/path/to/clang-cl.exe' +# with clang-cl, so this is special in that it only compiles LLVM with clang-cl. +# Note that this takes a /path/to/clang-cl, not a boolean. +#clang-cl = cc # Pass extra compiler and linker flags to the LLVM CMake build. -#cflags = "-fextra-flag" -#cxxflags = "-fextra-flag" -#ldflags = "-Wl,extra-flag" +#cflags = "" +#cxxflags = "" +#ldflags = "" # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure # that your host compiler ships with libc++. -#use-libcxx = true +#use-libcxx = false # The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake. -#use-linker = "lld" +#use-linker = (path) # Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` #allow-old-toolchain = false @@ -147,6 +149,9 @@ # General build configuration options # ============================================================================= [build] +# The default stage to use for the `check` subcommand +#check-stage = 0 + # The default stage to use for the `doc` subcommand #doc-stage = 0 @@ -170,14 +175,14 @@ # binaries of this build triple and the nightly will be used to bootstrap the # first compiler. # -# Defaults to host platform -#build = "x86_64-unknown-linux-gnu" +# Defaults to platform where `x.py` is run. +#build = "x86_64-unknown-linux-gnu" (as an example) # Which triples to produce a compiler toolchain for. Each of these triples will # be bootstrapped from the build triple themselves. # -# Defaults to just the build triple -#host = ["x86_64-unknown-linux-gnu"] +# Defaults to just the build triple. +#host = ["x86_64-unknown-linux-gnu"] (as an example) # Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of # these triples will be bootstrapped from the build triple themselves. @@ -185,7 +190,7 @@ # Defaults to `host`. If you set this explicitly, you likely want to add all # host triples to this list as well in order for those host toolchains to be # able to compile programs for their native target. -#target = ["x86_64-unknown-linux-gnu"] +#target = ["x86_64-unknown-linux-gnu"] (as an example) # Use this directory to store build artifacts. # You can use "$ROOT" to indicate the root of the git repository. @@ -193,15 +198,15 @@ # Instead of downloading the src/stage0.txt version of Cargo specified, use # this Cargo binary instead to build all Rust code -#cargo = "/path/to/bin/cargo" +#cargo = "/path/to/cargo" # Instead of downloading the src/stage0.txt version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. -#rustc = "/path/to/bin/rustc" +#rustc = "/path/to/rustc" # Instead of download the src/stage0.txt version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. -#rustfmt = "/path/to/bin/rustfmt" +#rustfmt = "/path/to/rustfmt" # Flag to specify whether any documentation is built. If false, rustdoc and # friends will still be compiled but they will not be used to generate any @@ -259,10 +264,11 @@ # be built if `extended = true`. #extended = false -# Installs chosen set of extended tools if `extended = true`. By default builds all. -# If chosen tool failed to build the installation fails. If `extended = false`, this -# option is ignored. -#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] +# Installs chosen set of extended tools if `extended = true`. By default builds +# all extended tools except `rust-demangler`, unless the target is also being +# built with `profiler = true`. If chosen tool failed to build the installation +# fails. If `extended = false`, this option is ignored. +#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] # + "rust-demangler" if `profiler` # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose #verbose = 0 @@ -325,16 +331,9 @@ # Where to install man pages in `prefix` above #mandir = "share/man" -# Where to install data in `prefix` above (currently unused) +# Where to install data in `prefix` above #datadir = "share" -# Where to install additional info in `prefix` above (currently unused) -#infodir = "share/info" - -# Where to install local state (currently unused) -# If this is a relative path, it will get installed in `prefix` above -#localstatedir = "/var/lib" - # ============================================================================= # Options for compiling Rust code itself # ============================================================================= @@ -372,7 +371,9 @@ # Whether to download the stage 1 and 2 compilers from CI. # This is mostly useful for tools; if you have changes to `compiler/` they will be ignored. # -# FIXME: currently, this also uses the downloaded compiler for stage0, but that causes unnecessary rebuilds. +# You can set this to "if-unchanged" to only download if `compiler/` has not been modified. +# +# FIXME(#82739): currently, this also uses the downloaded compiler for stage0, but that causes unnecessary rebuilds. #download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 @@ -384,7 +385,9 @@ # Sets the number of codegen units to build the standard library with, # regardless of what the codegen-unit setting for the rest of the compiler is. -#codegen-units-std = 1 +# NOTE: building with anything other than 1 is known to occasionally have bugs. +# See https://github.com/rust-lang/rust/issues/83600. +#codegen-units-std = codegen-units # Whether or not debug assertions are enabled for the compiler and standard # library. Debug assertions control the maximum log level used by rustc. When @@ -427,19 +430,13 @@ #debuginfo-level = 0 # Debuginfo level for the compiler. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-rustc = 0 +#debuginfo-level-rustc = debuginfo-level # Debuginfo level for the standard library. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-std = 0 +#debuginfo-level-std = debuginfo-level # Debuginfo level for the tools. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-tools = 0 +#debuginfo-level-tools = debuginfo-level # Debuginfo level for the test suites run with compiletest. # FIXME(#61117): Some tests fail when this option is enabled. @@ -466,7 +463,9 @@ # 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. -#default-linker = "cc" +# +# See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. +#default-linker = (path) # The "channel" for the Rust build to produce. The stable/beta channels only # allow using stable features, whereas the nightly and dev channels allow using @@ -476,10 +475,15 @@ # A descriptive string to be appended to `rustc --version` output, which is # also used in places like debuginfo `DW_AT_producer`. This may be useful for # supplementary build information, like distro-specific package versions. -#description = "" +#description = (string) -# The root location of the musl installation directory. -#musl-root = "..." +# The root location of the musl installation directory. The library directory +# will also need to contain libunwind.a for an unwinding implementation. Note +# that this option only makes sense for musl targets that produce statically +# linked binaries. +# +# Defaults to /usr on musl hosts. Has no default otherwise. +#musl-root = (path) # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix # platforms to ensure that the compiler is usable by default from the build @@ -502,14 +506,14 @@ # Having the git information can cause a lot of rebuilds during development. # Note: If this attribute is not explicitly set (e.g. if left commented out) it # will default to true if channel = "dev", but will default to false otherwise. -#ignore-git = true +#ignore-git = if channel == "dev" { true } else { false } # When creating source tarballs whether or not to create a source tarball. -#dist-src = false +#dist-src = true # After building or testing extended tools (e.g. clippy and rustfmt), append the # result (broken, compiling, testing) into this JSON file. -#save-toolstates = "/path/to/toolstates.json" +#save-toolstates = (path) # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, @@ -545,9 +549,7 @@ # Compile the compiler with a non-default ThinLTO import limit. This import # limit controls the maximum size of functions imported by ThinLTO. Decreasing # will make code compile faster at the expense of lower runtime performance. -# If `incremental` is set to true above, the import limit will default to 10 -# instead of LLVM's default of 100. -#thin-lto-import-instr-limit = 100 +#thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } # Map debuginfo paths to `/rust/$sha/...`, generally only set for releases #remap-debuginfo = false @@ -581,63 +583,66 @@ # ============================================================================= [target.x86_64-unknown-linux-gnu] -# C compiler to be used to compiler C code. Note that the +# C compiler to be used to compile C code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. -#cc = "cc" +# See `src/bootstrap/cc_detect.rs` for details. +#cc = "cc" (path) -# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims). +# C++ compiler to be used to compile C++ code (e.g. LLVM and our LLVM shims). # This is only used for host targets. -#cxx = "c++" +# See `src/bootstrap/cc_detect.rs` for details. +#cxx = "c++" (path) # Archiver to be used to assemble static libraries compiled from C/C++ code. # Note: an absolute path should be used, otherwise LLVM build will break. -#ar = "ar" +#ar = "ar" (path) # Ranlib to be used to assemble static libraries compiled from C/C++ code. # Note: an absolute path should be used, otherwise LLVM build will break. -#ranlib = "ranlib" +#ranlib = "ranlib" (path) -# Linker to be used to link Rust code. Note that the +# Linker to be used to bootstrap Rust code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. # Setting this will override the `use-lld` option for Rust code when targeting MSVC. -#linker = "cc" +#linker = "cc" (path) # Path to the `llvm-config` binary of the installation of a custom LLVM to link # against. Note that if this is specified we don't compile LLVM at all for this # target. -#llvm-config = "../path/to/llvm/root/bin/llvm-config" +#llvm-config = (path) # Normally the build system can find LLVM's FileCheck utility, but if # not, you can specify an explicit file name for it. -#llvm-filecheck = "/path/to/FileCheck" +#llvm-filecheck = "/path/to/llvm-version/bin/FileCheck" # If this target is for Android, this option will be required to specify where # the NDK for the target lives. This is used to find the C compiler to link and # build native code. -#android-ndk = "/path/to/ndk" +# See `src/bootstrap/cc_detect.rs` for details. +#android-ndk = (path) # Build the sanitizer runtimes for this target. # This option will override the same option under [build] section. -#sanitizers = false +#sanitizers = build.sanitizers (bool) # Build the profiler runtime for this target(required when compiling with options that depend # on this runtime, such as `-C profile-generate` or `-Z instrument-coverage`). # This option will override the same option under [build] section. -#profiler = false +#profiler = build.profiler (bool) # Force static or dynamic linkage of the standard library for this target. If # this target is a host for rustc, this will also affect the linkage of the # compiler itself. This is useful for building rustc on targets that normally # only use static libraries. If unset, the target's default linkage is used. -#crt-static = false +#crt-static = (bool) # The root location of the musl installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note # that this option only makes sense for musl targets that produce statically -# linked binaries -#musl-root = "..." +# linked binaries. +#musl-root = build.musl-root (path) # The full path to the musl libdir. #musl-libdir = musl-root/lib @@ -645,11 +650,11 @@ # The root location of the `wasm32-wasi` sysroot. Only used for the # `wasm32-wasi` target. If you are building wasm32-wasi target, make sure to # create a `[target.wasm32-wasi]` section and move this field there. -#wasi-root = "..." +#wasi-root = (path) # Used in testing for configuring where the QEMU images are located, you # probably don't want to use this. -#qemu-rootfs = "..." +#qemu-rootfs = (path) # ============================================================================= # Distribution options @@ -666,12 +671,7 @@ # # This folder should be populated ahead of time before the build system is # invoked. -#sign-folder = "path/to/folder/to/sign" - -# This is a file which contains the password of the default gpg key. This will -# be passed to `gpg` down the road when signing all files in `sign-folder` -# above. This should be stored in plaintext. -#gpg-password-file = "path/to/gpg/password" +#sign-folder = (path) # The remote address that all artifacts will eventually be uploaded to. The # build system generates manifests which will point to these urls, and for the @@ -679,18 +679,19 @@ # # Note that this address should not contain a trailing slash as file names will # be appended to it. -#upload-addr = "https://example.com/folder" +#upload-addr = (URL) # Whether to build a plain source tarball to upload # We disable that on Windows not to override the one already uploaded on S3 # as the one built on Windows will contain backslashes in paths causing problems # on linux #src-tarball = true -# # Whether to allow failures when building tools #missing-tools = false # List of compression formats to use when generating dist tarballs. The list of # formats is provided to rust-installer, which must support all of them. +# +# This list must be non-empty. #compression-formats = ["gz", "xz"] diff -Nru rustc-1.52.1+dfsg1+llvm/debian/changelog rustc-1.53.0+dfsg1+llvm/debian/changelog --- rustc-1.52.1+dfsg1+llvm/debian/changelog 2021-10-22 00:59:10.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/changelog 2021-10-28 20:27:28.000000000 +0000 @@ -1,10 +1,85 @@ -rustc (1.52.1+dfsg1+llvm-1ubuntu1~21.04.1) hirsute; urgency=medium +rustc (1.53.0+dfsg1+llvm-4ubuntu1~21.04.1) hirsute; urgency=medium + [ Michael Hudson-Doyle ] * Backport to Hirsute. (LP: #1943842) * Do not run tests on armhf as they hang. * Drop adjustment of -march setting on armhf. - -- Michael Hudson-Doyle Fri, 22 Oct 2021 13:59:10 +1300 + -- Olivier Tilloy Thu, 28 Oct 2021 22:27:28 +0200 + +rustc (1.53.0+dfsg1+llvm-4ubuntu1) UNRELEASED; urgency=medium + + * Merge 1.53.0+dfsg1-4 from Debian unstable. (LP: #1943842) + Remaining changes: + - Use the bundled llvm to avoid having to do llvm updates in order to + deliver rust updates + - update debian/config.toml.in + - update debian/control + - update debian/copyright + - update debian/rules + - Build-Depend on libc6-dbg on armhf, to workaround a crash in ld.so + during some debuginfo tests + - update debian/control + - Add a hack to ensure the stage0 compiler is extracted to the correct + location + - update debian/make_orig-stage0_tarball.sh + - Scrub -g from CFLAGS and CXXFLAGS in order to let rustbuild control + whether LLVM is compiled with debug symbols + - update debian/rules + - On i386, only build debuginfo for libstd + - update debian/rules + - Ignore all test failures on every architecture + - update debian/rules + - Version the Build-Conflict on gdb-minimal as gdb now Provides it + - update debian/control + - Adjust the rustc Breaks/Replaces libstd-rust-dev version to fix an + upgrade issue + - update debian/control + - Adjust debian/watch to include +llvm in upstream version. + - update debian/watch + - 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. + - Reduce parallelism on all arches to avoid OOMs during build. + - Adjust -march setting on armhf + + -- Michael Hudson-Doyle Tue, 26 Oct 2021 16:04:30 +1300 + +rustc (1.53.0+dfsg1-4) unstable; urgency=medium + + * Ignore some hanging test regressions on non-release arches powerpc, ppc64. + + -- Ximin Luo Wed, 06 Oct 2021 19:24:11 +0100 + +rustc (1.53.0+dfsg1-3) unstable; urgency=medium + + * Disable patch that was backported incorrectly. + * Temporarily increase armhf allowed-failures to 12. + + -- Ximin Luo Wed, 06 Oct 2021 19:01:54 +0100 + +rustc (1.53.0+dfsg1-2) unstable; urgency=medium + + * Fix some test failures. + + -- Ximin Luo Wed, 06 Oct 2021 10:29:03 +0100 + +rustc (1.53.0+dfsg1-1) unstable; urgency=medium + + * Upload to unstable. + * Update mips patches, disable a test as our workaround makes it invalid. + * Temporarily ignore some tests that fail on big-endian. + + -- Ximin Luo Tue, 05 Oct 2021 23:19:31 +0100 + +rustc (1.53.0+dfsg1-1~exp1) experimental; urgency=medium + + * New upstream release. (Closes: #986803) + * Honour parallel option in DEB_BUILD_OPTIONS. (Closes: #993871) + + -- Ximin Luo Sat, 02 Oct 2021 12:46:49 +0100 rustc (1.52.1+dfsg1+llvm-1ubuntu1) impish; urgency=medium diff -Nru rustc-1.52.1+dfsg1+llvm/debian/config.toml.in rustc-1.53.0+dfsg1+llvm/debian/config.toml.in --- rustc-1.52.1+dfsg1+llvm/debian/config.toml.in 2021-10-13 01:17:36.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/config.toml.in 2021-10-28 20:25:55.000000000 +0000 @@ -1,3 +1,5 @@ +changelog-seen = 2 + [build] submodules = false vendor = true diff -Nru rustc-1.52.1+dfsg1+llvm/debian/control rustc-1.53.0+dfsg1+llvm/debian/control --- rustc-1.52.1+dfsg1+llvm/debian/control 2021-10-22 00:56:51.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/control 2021-10-28 20:26:06.000000000 +0000 @@ -14,8 +14,8 @@ dpkg-dev (>= 1.17.14), python3:native, cargo:native (>= 0.40.0) , - rustc:native (>= 1.51.0+dfsg) , - rustc:native (<= 1.52.1++) , + rustc:native (>= 1.52.0+dfsg) , + rustc:native (<= 1.53.0++) , cmake (>= 3.0) | cmake3, # needed by some vendor crates pkg-config, @@ -54,7 +54,7 @@ libstd-rust-dev (= ${binary:Version}), gcc, libc-dev, binutils (>= 2.26) Recommends: - cargo (>= 0.53.0~~), cargo (<< 0.54.0~~), + cargo (>= 0.54.0~~), cargo (<< 0.55.0~~), # llvm is needed for llvm-dwp for -C split-debuginfo=packed llvm-12, Suggests: @@ -75,7 +75,7 @@ generic programming and meta-programming, in both static and dynamic styles. -Package: libstd-rust-1.52 +Package: libstd-rust-1.53 Section: libs Architecture: any Multi-Arch: same @@ -102,7 +102,7 @@ Architecture: any Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends}, - libstd-rust-1.52 (= ${binary:Version}), + libstd-rust-1.53 (= ${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 @@ -209,7 +209,7 @@ Architecture: any Multi-Arch: allowed Depends: ${misc:Depends}, ${shlibs:Depends}, - libstd-rust-1.52 (= ${binary:Version}) + libstd-rust-1.53 (= ${binary:Version}) Recommends: cargo Description: Rust linter Rust is a curly-brace, block-structured expression language. It @@ -264,7 +264,7 @@ rust-gdb (>= ${binary:Version}) | rust-lldb (>= ${binary:Version}), cargo, Recommends: - cargo (>= 0.53.0~~), cargo (<< 0.54.0~~) + cargo (>= 0.54.0~~), cargo (<< 0.55.0~~) Suggests: rust-doc (>= ${binary:Version}), rust-src (>= ${binary:Version}), diff -Nru rustc-1.52.1+dfsg1+llvm/debian/copyright rustc-1.53.0+dfsg1+llvm/debian/copyright --- rustc-1.52.1+dfsg1+llvm/debian/copyright 2021-10-13 01:17:36.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/copyright 2021-10-28 20:25:55.000000000 +0000 @@ -4,9 +4,7 @@ Files-Excluded: *.min.js src/llvm-emscripten - vendor/jemalloc-sys - vendor/libmimalloc-sys - vendor/mimalloc + src/llvm-project vendor/mdbook/src/theme/fonts vendor/mdbook/src/theme/FontAwesome vendor/mdbook/src/theme/highlight.js @@ -46,10 +44,10 @@ vendor/adler-0.2.3 vendor/always-assert vendor/anyhow-1.0.34 + vendor/anyhow-1.0.38 vendor/anymap vendor/ar vendor/array_tool - vendor/arrayvec-0.5.1 vendor/autocfg-1.0.0 vendor/backtrace vendor/bitmaps @@ -66,11 +64,8 @@ vendor/chalk-ir vendor/chalk-recursive vendor/chalk-solve - vendor/cloudabi vendor/commoncrypto vendor/commoncrypto-sys - vendor/compiletest_rs-0.5.0 - vendor/const_fn vendor/core-foundation vendor/core-foundation-sys vendor/countme @@ -86,7 +81,7 @@ vendor/cranelift-native vendor/cranelift-object vendor/crc32fast-1.2.0 - vendor/crossbeam-utils-0.8.0 + vendor/crossbeam-channel-0.5.0 vendor/crypto-hash vendor/curl vendor/curl-sys @@ -95,6 +90,8 @@ vendor/directories vendor/drop_bomb vendor/either-1.6.0 + vendor/enum-iterator + vendor/enum-iterator-derive vendor/env_logger-0.6.2 vendor/env_logger-0.8.1 vendor/env_logger @@ -105,10 +102,11 @@ vendor/flate2-1.0.16 vendor/foreign-types vendor/foreign-types-shared + vendor/fs-err vendor/fsevent vendor/fsevent-sys vendor/fs_extra-1.1.0 - vendor/fst-0.3.5 + vendor/fs_extra vendor/fst vendor/fuchsia-zircon vendor/fuchsia-zircon-sys @@ -124,6 +122,7 @@ vendor/futures-util vendor/fwdansi vendor/gcc + vendor/getset vendor/git2 vendor/git2-curl vendor/heck-0.3.1 @@ -144,6 +143,7 @@ vendor/itoa-0.4.6 vendor/jemallocator vendor/jemalloc-ctl + vendor/jemalloc-sys vendor/jod-thread vendor/json vendor/jsonpath_lib @@ -173,6 +173,7 @@ vendor/lsp-types vendor/mach vendor/memchr-2.3.3 + vendor/memmap2-0.2.1 vendor/mimalloc vendor/miniz_oxide-0.4.0 vendor/mio-0.6.22 @@ -180,6 +181,7 @@ vendor/mio-named-pipes vendor/mio-uds vendor/miow-0.2.2 + vendor/miow-0.3.6 vendor/net2 vendor/notify vendor/ntapi @@ -193,8 +195,6 @@ vendor/openssl-sys vendor/ordslice vendor/parity-tokio-ipc - vendor/parking_lot-0.11.0 - vendor/parking_lot_core-0.8.0 vendor/paste vendor/paste-impl vendor/percent-encoding-1.0.1 @@ -203,26 +203,41 @@ vendor/pin-project-lite-0.2.4 vendor/pin-utils vendor/pretty_env_logger - vendor/proc-macro2-1.0.19 + vendor/proc-macro2-1.0.24 vendor/proc-macro-crate vendor/proc-macro-hack vendor/proc-macro-nested vendor/pulldown-cmark-to-cmark vendor/quote-1.0.7 vendor/racer - vendor/rand - vendor/rand_chacha - vendor/rand_core - vendor/rand_hc vendor/rand_xoshiro vendor/rayon-1.3.1 vendor/rayon-core-1.7.1 + vendor/redox_syscall-0.2.5 vendor/regalloc + vendor/regex-1.4.3 + vendor/regex-syntax-0.6.22 vendor/region - vendor/rls-analysis vendor/rls-vfs vendor/rowan + vendor/rustc-ap-rustc_arena + vendor/rustc-ap-rustc_ast + vendor/rustc-ap-rustc_ast_pretty + vendor/rustc-ap-rustc_data_structures + vendor/rustc-ap-rustc_errors + vendor/rustc-ap-rustc_feature + vendor/rustc-ap-rustc_fs_util + vendor/rustc-ap-rustc_graphviz + vendor/rustc-ap-rustc_index + vendor/rustc-ap-rustc_lexer-716.0.0 vendor/rustc-ap-rustc_lexer + vendor/rustc-ap-rustc_lint_defs + vendor/rustc-ap-rustc_macros + vendor/rustc-ap-rustc_parse + vendor/rustc-ap-rustc_serialize + vendor/rustc-ap-rustc_session + vendor/rustc-ap-rustc_span + vendor/rustc-ap-rustc_target vendor/rustc_version vendor/salsa vendor/salsa-macros @@ -230,38 +245,38 @@ vendor/security-framework vendor/security-framework-sys vendor/semver-0.9.0 - vendor/serde-1.0.118 - vendor/serde_derive-1.0.118 vendor/serde_ignored vendor/serde_json-1.0.59 vendor/serde_path_to_error vendor/serde_repr - vendor/shell-escape vendor/shlex-0.1.1 vendor/signal-hook-registry vendor/sized-chunks vendor/slab - vendor/smallvec-0.6.14 vendor/smol_str vendor/snap-1.0.1 - vendor/socket2-0.3.16 + vendor/socket2 vendor/strip-ansi-escapes - vendor/syn-1.0.38 vendor/syn-1.0.60 + vendor/syn-1.0.65 vendor/target-lexicon vendor/termcolor-1.1.0 - vendor/tester-0.7.0 vendor/text-size vendor/thiserror-1.0.20 vendor/thiserror-impl-1.0.20 vendor/thread_local-1.0.1 vendor/threadpool + vendor/tikv-jemallocator + vendor/tikv-jemalloc-sys vendor/tinyvec-0.3.4 vendor/tokio vendor/tokio-macros vendor/tokio-util vendor/tower-service + vendor/tracing-attributes-0.1.13 + vendor/tracing-subscriber-0.2.16 vendor/ungrammar + vendor/unicode-bidi-0.3.4 vendor/unicode-normalization-0.1.13 vendor/unicode-segmentation-1.6.0 vendor/url-1.7.2 @@ -271,6 +286,7 @@ vendor/vergen vendor/version_check-0.9.1 vendor/vte + vendor/walkdir-2.3.1 vendor/winapi-0.2.8 vendor/winapi-build vendor/write-json @@ -354,6 +370,13 @@ License: MIT or Apache-2.0 Comment: see https://github.com/rust-lang-nursery/compiler-builtins +Files: vendor/compiletest_rs/* +Copyright: 2015-2020 The Rust Project Developers + 2015-2020 Thomas Bracht Laumann Jespersen + 2015-2020 Manish Goregaokar +License: Apache-2.0 or MIT +Comment: see https://github.com/laumann/compiletest-rs + Files: vendor/bitflags/* vendor/cc/* @@ -377,11 +400,6 @@ same MIT/Apache-2.0 dual-license. See https://github.com/rust-lang. Exceptions are noted below. -Files: vendor/adler/* -Copyright: 2020-2020 Jonas Schievink -License: 0BSD or MIT or Apache-2.0 -Comment: see https://github.com/jonas-schievink/adler.git - Files: vendor/num-integer/* vendor/num-traits/* Copyright: 2014-2018 The Rust Project Developers @@ -459,6 +477,16 @@ Copyright: 2000-2012 Doug Lea License: CC0-1.0 +Files: vendor/tester/* +Copyright: 2016-2019 The Rust Project Developers +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/* Copyright: 2016-2020 Nick Fitzgerald 2016-2020 Philip Craig @@ -467,6 +495,11 @@ License: Apache-2.0 or MIT Comment: see https://github.com/gimli-rs/addr2line +Files: vendor/adler/* +Copyright: 2020-2020 Jonas Schievink +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 @@ -478,7 +511,7 @@ Comment: see https://github.com/notriddle/ammonia Files: vendor/annotate-snippets/* -Copyright: 2018-2019 Zibi Braniecki +Copyright: 2018-2020 Zibi Braniecki License: Apache-2.0 or MIT Comment: see https://github.com/zbraniecki/annotate-snippets-rs @@ -531,6 +564,11 @@ 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*/* @@ -558,6 +596,12 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/BurntSushi/bstr +Files: vendor/bytecount/* +Copyright: 2016-2020 Andre Bogus + 2016-2020 Joshua Landau +License: Apache-2.0 or MIT +Comment: see https://github.com/llogiq/bytecount + Files: vendor/byteorder/* vendor/fst/* @@ -643,6 +687,11 @@ 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/* @@ -707,6 +756,11 @@ License: Apache-2.0 or MIT Comment: see https://github.com/rust-lang-nursery/datafrog +Files: vendor/derive-new/* +Copyright: 2016-2020 Nick Cameron +License: MIT +Comment: see https://github.com/nrc/derive-new + Files: vendor/diff/* Copyright: 2015-2017 Utkarsh Kukreti License: MIT or Apache-2.0 @@ -757,6 +811,23 @@ License: MIT Comment: see https://github.com/johannhof/difference.rs +Files: + vendor/dirs/* + vendor/dirs-sys/* +Copyright: 2015-2020 Simon Ochsenreither + 2015-2020 dirs-rs contributors +License: MIT OR Apache-2.0 +Comment: + see https://github.com/dirs-dev/dirs-rs + see https://github.com/dirs-dev/dirs-sys-rs + +Files: + vendor/dirs-next/* + vendor/dirs-sys-next/* +Copyright: 2017-2021 The @xdg-rs members +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 @@ -898,16 +969,24 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/brson/home -Files: vendor/humantime/* -Copyright: 2016-2018 Paul Colomiets +Files: vendor/humantime-*/* +Copyright: + 2016-2018 Paul Colomiets + 2016 The humantime Developers + 2016 Pyfisch + 2005-2013 Rich Felker License: MIT or Apache-2.0 -Comment: see https://github.com/tailhook/humantime 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 +Comment: see https://github.com/lfairy/if_chain + Files: vendor/form_urlencoded/* vendor/idna/* @@ -987,6 +1066,11 @@ License: ISC Comment: see https://github.com/nagisa/rust_libloading/ +Files: vendor/libm/* +Copyright: 2018-2021 Jorge Aparicio +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 @@ -1165,6 +1249,12 @@ see https://github.com/Amanieu/thread_local-rs see https://github.com/Amanieu/parking_lot +Files: vendor/packed_simd_2/* +Copyright: 2018-2021 Gonzalo Brito Gadeschi + 2018-2021 Jubilee Young +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang-nursery/packed_simd + Files: vendor/paste/* vendor/paste-impl/* @@ -1281,6 +1371,11 @@ License: MIT or Apache-2.0 Comment: see http://github.com/tailhook/quick-error +Files: vendor/quine-mc_cluskey/* +Copyright: 2016-2016 Oliver Schneider +License: MIT +Comment: see https://github.com/oli-obk/quine-mc_cluskey + Files: vendor/rayon/* vendor/rayon-core/* @@ -1294,6 +1389,14 @@ see https://github.com/Zoxc/rayon/tree/rustc Files: + vendor/redox_users/* + vendor/redox_users-0*/* +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/* @@ -1330,13 +1433,6 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/matklad/rowan -Files: - vendor/rustc-ap-rustc_lexer/* - vendor/rustc-ap-rustc_lexer-*/* -Copyright: 2010-2020 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang/rust - Files: vendor/rustc-semver/* Copyright: 2020-2020 flip1995 License: MIT OR Apache-2.0 @@ -1427,16 +1523,21 @@ License: MIT Comment: see https://github.com/hawkw/sharded-slab -Files: vendor/siphasher/* -Copyright: 2016-2018 Frank Denis +Files: vendor/shell-escape/* +Copyright: 2016-2020 Steven Fackler License: MIT or Apache-2.0 -Comment: see https://github.com/jedisct1/rust-siphash +Comment: see https://github.com/sfackler/shell-escape Files: vendor/shlex/* Copyright: 2015-2015 comex License: MIT or Apache-2.0 Comment: see https://github.com/comex/rust-shlex +Files: vendor/siphasher/* +Copyright: 2016-2018 Frank Denis +License: MIT or Apache-2.0 +Comment: see https://github.com/jedisct1/rust-siphash + Files: vendor/smallvec-0*/* vendor/smallvec/* @@ -1471,6 +1572,14 @@ Comment: see https://github.com/dguo/strsim-rs Files: + vendor/structopt/* + vendor/structopt-derive/* +Copyright: 2017-2020 Guillaume Pinot + 2017-2020 others +License: Apache-2.0 OR MIT +Comment: see https://github.com/TeXitoi/structopt + +Files: vendor/strum/* vendor/strum_macros/* Copyright: 2015-2018 Peter Glotfelty @@ -1504,6 +1613,15 @@ License: MIT or Apache-2.0 Comment: see https://github.com/servo/tendril +Files: + vendor/term/* + vendor/term-0*/* +Copyright: + 2014-2021 The Rust Project Developers + 2014-2021 Steven Allen +License: MIT or Apache-2.0 +Comment: see https://github.com/Stebalien/term + Files: vendor/termion/* Copyright: 2016-2017 ticki 2016-2017 gycos @@ -1548,6 +1666,13 @@ License: MIT OR Apache-2.0 Comment: see https://github.com/cad97/thin-dst +Files: + vendor/thiserror/* + vendor/thiserror-impl/* +Copyright: 2019-2020 David Tolnay +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 @@ -1623,6 +1748,11 @@ License: MIT or Apache-2.0 Comment: see https://github.com/seanmonstar/unicase +Files: vendor/unicode_categories/* +Copyright: 2015-2016 Sean Gillespie +License: MIT OR Apache-2.0 +Comment: see https://github.com/swgillespie/unicode-categories + Files: vendor/unicode-normalization/* vendor/unicode-segmentation/* @@ -1642,12 +1772,28 @@ License: MIT or Apache-2.0 Comment: see https://github.com/unicode-rs/unicode-xid +Files: vendor/unicode-script/* +Copyright: 2017-2020 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/unicode-rs/unicode-script + +Files: vendor/unicode-security/* +Copyright: 2020-2020 Charles Lew + 2020-2020 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/unicode-rs/unicode-security + Files: vendor/unified-diff/* Copyright: 2021-2021 Michael Howell 2021-2021 The Rust Project Developers License: MIT OR Apache-2.0 Comment: see https://github.com/notriddle/rust-unified-diff +Files: vendor/utf-8/* +Copyright: 2015-2018 Simon Sapin +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 @@ -1661,11 +1807,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/contain-rs/vec-map -Files: vendor/utf-8/* -Copyright: 2015-2018 Simon Sapin -License: MIT OR Apache-2.0 -Comment: see https://github.com/SimonSapin/rust-utf8 - Files: vendor/wasi-0*/* vendor/wasi/* @@ -1711,147 +1852,13 @@ License: MIT or Apache-2.0 Comment: see https://github.com/chyh1990/yaml-rust -Files: vendor/humantime-1.3.0/* -Copyright: - 2016-2018 Paul Colomiets - 2016 The humantime Developers - 2016 Pyfisch - 2005-2013 Rich Felker -License: MIT or Apache-2.0 - -Files: vendor/unicode-script/* -Copyright: 2017-2020 Manish Goregaokar -License: MIT or Apache-2.0 -Comment: see https://github.com/unicode-rs/unicode-script - -Files: vendor/unicode-security/* -Copyright: 2020-2020 Charles Lew - 2020-2020 Manish Goregaokar -License: MIT or Apache-2.0 -Comment: see https://github.com/unicode-rs/unicode-security - -Files: vendor/blake2b_simd/* -Copyright: 2018-2020 Jack O'Connor -License: MIT -Comment: see https://github.com/oconnor663/blake2_simd - -Files: vendor/compiletest_rs/* -Copyright: 2015-2020 The Rust Project Developers - 2015-2020 Thomas Bracht Laumann Jespersen - 2015-2020 Manish Goregaokar -License: Apache-2.0 or MIT -Comment: see https://github.com/laumann/compiletest-rs - -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/derive-new/* -Copyright: 2016-2020 Nick Cameron -License: MIT -Comment: see https://github.com/nrc/derive-new - -Files: - vendor/dirs/* - vendor/dirs-sys/* -Copyright: 2015-2020 Simon Ochsenreither - 2015-2020 dirs-rs contributors -License: MIT OR Apache-2.0 -Comment: - see https://github.com/dirs-dev/dirs-rs - see https://github.com/dirs-dev/dirs-sys-rs - -Files: - vendor/dirs-next/* - vendor/dirs-sys-next/* -Copyright: 2017-2021 The @xdg-rs members -License: MIT OR Apache-2.0 -Comment: see https://github.com/xdg-rs/dirs - -Files: vendor/if_chain/* -Copyright: 2016-2020 Chris Wong -License: MIT or Apache-2.0 -Comment: see https://github.com/lfairy/if_chain - -Files: vendor/measureme-0.7.1/* -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/quine-mc_cluskey/* -Copyright: 2016-2016 Oliver Schneider -License: MIT -Comment: see https://github.com/oli-obk/quine-mc_cluskey - -Files: - vendor/redox_users/* - vendor/redox_users-0*/* -Copyright: 2017-2021 Jose Narvaez - 2017-2021 Wesley Hershberger +Files: vendor/yansi-term/* +Copyright: 2014-2020 ogham@bsago.me + 2014-2020 Ryan Scheel (Havvy) + 2014-2020 Josh Triplett + 2014-2020 Juan Aguilar Santillana License: MIT -Comment: see https://gitlab.redox-os.org/redox-os/users - -Files: vendor/rust-argon2/* -Copyright: 2017-2020 Martijn Rijkeboer -License: MIT or Apache-2.0 -Comment: see https://github.com/sru-systems/rust-argon2 - -Files: - vendor/term/* - vendor/term-0*/* -Copyright: - 2014-2021 The Rust Project Developers - 2014-2021 Steven Allen -License: MIT or Apache-2.0 -Comment: see https://github.com/Stebalien/term - -Files: vendor/tester/* -Copyright: 2016-2019 The Rust Project Developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/messense/rustc-test - -Files: vendor/annotate-snippets-0*/* -Copyright: 2018-2020 Zibi Braniecki -License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang/annotate-snippets-rs - -Files: vendor/bytecount/* -Copyright: 2016-2020 Andre Bogus - 2016-2020 Joshua Landau -License: Apache-2.0 or MIT -Comment: see https://github.com/llogiq/bytecount - -Files: vendor/packed_simd/* -Copyright: 2018-2020 Gonzalo Brito Gadeschi -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang-nursery/packed_simd - -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/structopt/* - vendor/structopt-derive/* -Copyright: 2017-2020 Guillaume Pinot - 2017-2020 others -License: Apache-2.0 OR MIT -Comment: see https://github.com/TeXitoi/structopt - -Files: - vendor/thiserror/* - vendor/thiserror-impl/* -Copyright: 2019-2020 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/thiserror - -Files: vendor/unicode_categories/* -Copyright: 2015-2016 Sean Gillespie -License: MIT OR Apache-2.0 -Comment: see https://github.com/swgillespie/unicode-categories +Comment: see https://github.com/botika/yansi-term Files: debian/* Copyright: 2013-2018 Debian Rust Maintainers diff -Nru rustc-1.52.1+dfsg1+llvm/debian/libstd-rust-1.52.lintian-overrides rustc-1.53.0+dfsg1+llvm/debian/libstd-rust-1.52.lintian-overrides --- rustc-1.52.1+dfsg1+llvm/debian/libstd-rust-1.52.lintian-overrides 2021-10-06 01:50:23.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/libstd-rust-1.52.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -# "libstd" just seemed too generic -libstd-rust-1.52 binary: package-name-doesnt-match-sonames -libstd-rust-1.52 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.52 binary: dev-pkg-without-shlib-symlink -libstd-rust-1.52 binary: shlib-without-versioned-soname -libstd-rust-1.52 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.52 binary: library-not-linked-against-libc diff -Nru rustc-1.52.1+dfsg1+llvm/debian/libstd-rust-1.53.lintian-overrides rustc-1.53.0+dfsg1+llvm/debian/libstd-rust-1.53.lintian-overrides --- rustc-1.52.1+dfsg1+llvm/debian/libstd-rust-1.53.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/libstd-rust-1.53.lintian-overrides 2021-10-28 20:25:55.000000000 +0000 @@ -0,0 +1,13 @@ +# "libstd" just seemed too generic +libstd-rust-1.53 binary: package-name-doesnt-match-sonames +libstd-rust-1.53 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.53 binary: dev-pkg-without-shlib-symlink +libstd-rust-1.53 binary: shlib-without-versioned-soname +libstd-rust-1.53 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.53 binary: library-not-linked-against-libc diff -Nru rustc-1.52.1+dfsg1+llvm/debian/patches/d-0000-ignore-removed-submodules.patch rustc-1.53.0+dfsg1+llvm/debian/patches/d-0000-ignore-removed-submodules.patch --- rustc-1.52.1+dfsg1+llvm/debian/patches/d-0000-ignore-removed-submodules.patch 2021-10-06 01:50:23.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/patches/d-0000-ignore-removed-submodules.patch 2021-10-28 20:25:55.000000000 +0000 @@ -1,10 +1,24 @@ -Description: Ignore submodules that we're not building, or that are unused like - mdbook-linkcheck that pull in a ton of dependencies that are unneeded. -Author: Ximin Luo -Forwarded: not-needed +From: Debian Rust Maintainers +Date: Sat, 2 Oct 2021 01:07:59 +0100 +Subject: d-0000-ignore-removed-submodules + +--- + Cargo.toml | 27 --------------------------- + src/bootstrap/bootstrap.py | 4 ---- + src/bootstrap/builder.rs | 7 +------ + src/bootstrap/doc.rs | 1 - + src/bootstrap/test.rs | 9 +-------- + 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(+), 61 deletions(-) + +diff --git a/Cargo.toml b/Cargo.toml +index 327afe3..393586f 100644 --- a/Cargo.toml +++ b/Cargo.toml -@@ -16,23 +16,12 @@ +@@ -17,23 +17,12 @@ members = [ "src/tools/tidy", "src/tools/tier-check", "src/tools/build-manifest", @@ -28,7 +42,7 @@ ] exclude = [ -@@ -81,24 +70,8 @@ +@@ -84,25 +73,9 @@ gimli.debug = 0 miniz_oxide.debug = 0 object.debug = 0 @@ -39,13 +53,14 @@ -# vendored copy. -[patch."https://github.com/rust-lang/cargo"] -cargo = { path = "src/tools/cargo" } -- + cargo-util = { path = "src/tools/cargo/crates/cargo-util" } + -[patch."https://github.com/rust-lang/rustfmt"] -# Similar to Cargo above we want the RLS to use a vendored version of `rustfmt` -# that we're shipping as well (to ensure that the rustfmt in RLS and the -# `rustfmt` executable are the same exact version). -rustfmt-nightly = { path = "src/tools/rustfmt" } - +- [patch.crates-io] -# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on -# here @@ -53,9 +68,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 4111420..5891d6b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py -@@ -893,10 +893,6 @@ +@@ -912,10 +912,6 @@ class RustBuild(object): os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] for _ in range(1, self.verbose): args.append("--verbose") @@ -66,9 +83,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 cff1ec8..1a352d5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs -@@ -447,7 +447,6 @@ +@@ -449,7 +449,6 @@ impl<'a> Builder<'a> { doc::RustdocBook, doc::RustByExample, doc::RustcBook, @@ -76,7 +95,7 @@ doc::EmbeddedBook, doc::EditionGuide, ), -@@ -470,7 +469,6 @@ +@@ -473,7 +472,6 @@ impl<'a> Builder<'a> { dist::Miri, dist::LlvmTools, dist::RustDev, @@ -84,7 +103,7 @@ dist::BuildManifest, dist::ReproducibleArtifacts, ), -@@ -1456,10 +1454,7 @@ +@@ -1450,10 +1448,7 @@ impl<'a> Builder<'a> { } } @@ -96,9 +115,11 @@ cargo.arg("--frozen"); } +diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs +index a32b92e..52e209a 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs -@@ -60,7 +60,6 @@ +@@ -60,7 +60,6 @@ macro_rules! book { // NOTE: When adding a book here, make sure to ALSO build the book by // adding a build step in `src/bootstrap/builder.rs`! book!( @@ -106,9 +127,11 @@ EditionGuide, "src/doc/edition-guide", "edition-guide"; EmbeddedBook, "src/doc/embedded-book", "embedded-book"; Nomicon, "src/doc/nomicon", "nomicon"; +diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs +index 965d116..a25d42a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs -@@ -1642,14 +1642,7 @@ +@@ -1740,14 +1740,7 @@ impl Step for RustcGuide { } fn run(self, builder: &Builder<'_>) { @@ -124,22 +147,27 @@ } } ---- a/src/tools/tidy/src/deps.rs -+++ b/src/tools/tidy/src/deps.rs -@@ -374,8 +374,8 @@ - // 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. -- "cargo", -- "rustc-ap-rustc_ast", -+ //"cargo", -+ //"rustc-ap-rustc_ast", - ]; +diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml +index cade44a..accf9dc 100644 +--- a/src/tools/clippy/Cargo.toml ++++ b/src/tools/clippy/Cargo.toml +@@ -40,11 +40,6 @@ regex = "1.4" + quote = "1" + syn = { version = "1", features = ["full"] } - for &name in FORBIDDEN_TO_HAVE_DUPLICATES { +-# 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" +- + [build-dependencies] + rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } + +diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml +index 24b3b79..fbb31e2 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml -@@ -43,10 +43,10 @@ +@@ -43,10 +43,10 @@ regex = "1.0" term = "0.6" diff = "0.1" log = "0.4" @@ -152,7 +180,7 @@ bytecount = "0.6" unicode-width = "0.1.5" unicode_categories = "0.1.1" -@@ -59,11 +59,6 @@ +@@ -59,9 +59,4 @@ lazy_static = "1.0.0" anyhow = "1.0" thiserror = "1.0" @@ -161,12 +189,12 @@ -# for more information. -rustc-workspace-hack = "1.0.0" - - [dependencies.rustc_ast] - package = "rustc-ap-rustc_ast" - version = "705.0.0" + # Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. +diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs +index 9062a29..1705648 100644 --- a/src/tools/rustfmt/src/cargo-fmt/main.rs +++ b/src/tools/rustfmt/src/cargo-fmt/main.rs -@@ -529,7 +529,7 @@ +@@ -527,7 +527,7 @@ fn get_cargo_metadata( if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } @@ -175,17 +203,18 @@ match cmd.exec() { Ok(metadata) => Ok(metadata), ---- a/src/tools/clippy/Cargo.toml -+++ b/src/tools/clippy/Cargo.toml -@@ -38,11 +38,6 @@ - derive-new = "0.5" - regex = "1.4" - --# 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" -- - [build-dependencies] - rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } +diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs +index b604b39..6455a6a 100644 +--- a/src/tools/tidy/src/deps.rs ++++ b/src/tools/tidy/src/deps.rs +@@ -372,8 +372,8 @@ fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) { + // 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. +- "cargo", +- "rustc-ap-rustc_ast", ++ //"cargo", ++ //"rustc-ap-rustc_ast", + ]; + for &name in FORBIDDEN_TO_HAVE_DUPLICATES { diff -Nru rustc-1.52.1+dfsg1+llvm/debian/patches/d-0001-disable-miniz.patch rustc-1.53.0+dfsg1+llvm/debian/patches/d-0001-disable-miniz.patch --- rustc-1.52.1+dfsg1+llvm/debian/patches/d-0001-disable-miniz.patch 2021-10-06 01:50:23.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/patches/d-0001-disable-miniz.patch 2021-10-28 20:25:55.000000000 +0000 @@ -1,6 +1,16 @@ +From: Debian Rust Maintainers +Date: Sat, 2 Oct 2021 01:07:59 +0100 +Subject: d-0001-disable-miniz + +--- + vendor/flate2/Cargo.toml | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/vendor/flate2/Cargo.toml b/vendor/flate2/Cargo.toml +index 5352fb5..d3639ab 100644 --- a/vendor/flate2/Cargo.toml +++ b/vendor/flate2/Cargo.toml -@@ -45,10 +45,6 @@ +@@ -45,10 +45,6 @@ version = "1.1.0" optional = true default-features = false diff -Nru rustc-1.52.1+dfsg1+llvm/debian/patches/d-0002-pkg-config-no-special-snowflake.patch rustc-1.53.0+dfsg1+llvm/debian/patches/d-0002-pkg-config-no-special-snowflake.patch --- rustc-1.52.1+dfsg1+llvm/debian/patches/d-0002-pkg-config-no-special-snowflake.patch 2021-10-06 01:50:23.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/patches/d-0002-pkg-config-no-special-snowflake.patch 2021-10-28 20:25:55.000000000 +0000 @@ -1,3 +1,14 @@ +From: Debian Rust Maintainers +Date: Sat, 2 Oct 2021 01:08:00 +0100 +Subject: d-0002-pkg-config-no-special-snowflake + +--- + vendor/pkg-config/src/lib.rs | 22 ++++++++++------------ + vendor/pkg-config/tests/test.rs | 2 -- + 2 files changed, 10 insertions(+), 14 deletions(-) + +diff --git a/vendor/pkg-config/src/lib.rs b/vendor/pkg-config/src/lib.rs +index 2be11b3..0975563 100644 --- a/vendor/pkg-config/src/lib.rs +++ b/vendor/pkg-config/src/lib.rs @@ -9,8 +9,6 @@ @@ -9,7 +20,7 @@ //! * `FOO_NO_PKG_CONFIG` - if set, this will disable running `pkg-config` when //! probing for the library named `foo`. //! -@@ -106,9 +104,8 @@ +@@ -106,9 +104,8 @@ pub enum Error { /// Contains the name of the responsible environment variable. EnvNoPkgConfig(String), @@ -21,7 +32,7 @@ CrossCompilation, /// Failed to run `pkg-config`. -@@ -132,11 +129,6 @@ +@@ -132,11 +129,6 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { Error::EnvNoPkgConfig(ref name) => write!(f, "Aborted because {} is set", name), @@ -33,7 +44,7 @@ Error::Command { ref command, ref cause, -@@ -160,7 +152,7 @@ +@@ -160,7 +152,7 @@ impl fmt::Display for Error { } Ok(()) } @@ -42,7 +53,7 @@ } } } -@@ -321,6 +313,8 @@ +@@ -321,6 +313,8 @@ impl Config { if host == target { return true; } @@ -51,7 +62,7 @@ // pkg-config may not be aware of cross-compilation, and require // a wrapper script that sets up platform-specific prefixes. -@@ -380,7 +374,11 @@ +@@ -380,7 +374,11 @@ impl Config { fn command(&self, name: &str, args: &[&str]) -> Command { let exe = self .env_var_os("PKG_CONFIG") @@ -64,9 +75,11 @@ let mut cmd = Command::new(exe); if self.is_static(name) { cmd.arg("--static"); +diff --git a/vendor/pkg-config/tests/test.rs b/vendor/pkg-config/tests/test.rs +index 33a623c..0f934c4 100644 --- a/vendor/pkg-config/tests/test.rs +++ b/vendor/pkg-config/tests/test.rs -@@ -34,7 +34,6 @@ +@@ -34,7 +34,6 @@ fn find(name: &str) -> Result { pkg_config::probe_library(name) } @@ -74,7 +87,7 @@ fn cross_disabled() { let _g = LOCK.lock(); reset(); -@@ -46,7 +45,6 @@ +@@ -46,7 +45,6 @@ fn cross_disabled() { } } diff -Nru rustc-1.52.1+dfsg1+llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch rustc-1.53.0+dfsg1+llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch --- rustc-1.52.1+dfsg1+llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch 2021-10-06 01:50:23.000000000 +0000 +++ rustc-1.53.0+dfsg1+llvm/debian/patches/d-0003-mdbook-strip-embedded-libs.patch 2021-10-28 20:25:55.000000000 +0000 @@ -1,17 +1,23 @@ -Description: Use local web resources instead of remote ones -Author: Matthijs van Otterdijk -Author: Ximin Luo -Bug: https://github.com/azerupi/mdBook/issues/271 -Comment: - Use https://github.com/infinity0/mdBook/tree/debian to help you rebase the - patch on top of a newer version. - . - Make sure the paths here match the ones in debian/rust-doc.links +From: Debian Rust Maintainers +Date: Sat, 2 Oct 2021 01:08:00 +0100 +Subject: d-0003-mdbook-strip-embedded-libs + +Comment: Use https://github.com/infinity0/mdBook/tree/debian to help you rebase the patch on top of a newer version. . Make sure the paths here match the ones in debian/rust-doc.links --- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + src/tools/linkchecker/main.rs | 9 +++ + vendor/mdbook/src/book/init.rs | 6 -- + .../src/renderer/html_handlebars/hbs_renderer.rs | 80 ++----------------- + .../mdbook/src/renderer/html_handlebars/search.rs | 2 - + vendor/mdbook/src/theme/index.hbs | 93 +--------------------- + vendor/mdbook/src/theme/mod.rs | 27 ------- + vendor/mdbook/src/theme/searcher/mod.rs | 2 - + 7 files changed, 18 insertions(+), 201 deletions(-) + +diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs +index c677d04..4b55d50 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs -@@ -321,6 +321,15 @@ +@@ -319,6 +319,15 @@ fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Opti println!("`#{}` pointing to `{}`", fragment, pretty_path.display()); }; } @@ -27,132 +33,11 @@ } else { let pretty_path = path.strip_prefix(root).unwrap_or(&path); if !is_exception(file, pretty_path.to_str().unwrap()) { ---- a/vendor/mdbook/src/theme/index.hbs -+++ b/vendor/mdbook/src/theme/index.hbs -@@ -34,10 +34,7 @@ - {{/if}} - - -- -- {{#if copy_fonts}} -- -- {{/if}} -+ - - - -@@ -51,7 +48,7 @@ - - {{#if mathjax_support}} - -- -+ - {{/if}} - - -@@ -61,46 +58,6 @@ - var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}"; - - -- -- -- -- -- -- -- -- -- -